jkorstad commited on
Commit
aed7a0e
·
verified ·
1 Parent(s): 67d9fd3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -132
app.py CHANGED
@@ -111,46 +111,7 @@ df['url'] = 'https://huggingface.co/spaces/' + df['id']
111
 
112
  # ------------------------------------------------------
113
 
114
- def create_pagination_html(current_page, total_pages):
115
- """Create HTML for pagination links"""
116
- html = "<div style='text-align: center; margin: 20px 0;'>"
117
-
118
- # Calculate which page numbers to show
119
- if total_pages <= 7:
120
- pages_to_show = range(1, total_pages + 1)
121
- else:
122
- if current_page <= 4:
123
- pages_to_show = list(range(1, 6)) + ['...', total_pages]
124
- elif current_page >= total_pages - 3:
125
- pages_to_show = [1, '...'] + list(range(total_pages - 4, total_pages + 1))
126
- else:
127
- pages_to_show = [1, '...'] + list(range(current_page - 1, current_page + 2)) + ['...', total_pages]
128
-
129
- # Generate the HTML for page links
130
- for page in pages_to_show:
131
- if page == '...':
132
- html += f"<span style='margin: 0 5px;'>...</span>"
133
- else:
134
- if page == current_page:
135
- html += f"""
136
- <span style='margin: 0 5px; padding: 5px 10px;
137
- background-color: var(--color-accent-soft);
138
- border-radius: 5px; font-weight: bold;'>{page}</span>
139
- """
140
- else:
141
- html += f"""
142
- <button onclick='handlePageClick({page-1})'
143
- style='margin: 0 5px; padding: 5px 10px;
144
- border: 1px solid var(--color-border-primary);
145
- border-radius: 5px; cursor: pointer;
146
- background: none;'>{page}</button>
147
- """
148
-
149
- html += "</div>"
150
- return html
151
-
152
- def search_spaces(search_text="", category="All Categories", page=1, limit=100):
153
- # Filter spaces
154
  if category == "All Categories":
155
  spaces_df = df
156
  else:
@@ -159,57 +120,27 @@ def search_spaces(search_text="", category="All Categories", page=1, limit=100):
159
  if search_text:
160
  spaces_df = spaces_df[spaces_df['title'].str.lower().str.contains(search_text.lower())]
161
 
162
- # Sort by likes and get total count
163
- spaces_df = spaces_df.sort_values('likes', ascending=False)
164
  total_spaces = len(spaces_df)
165
- total_pages = max(1, (total_spaces + limit - 1) // limit)
166
- offset = (page - 1) * limit
167
 
168
- # Get the current page of spaces
169
- spaces = spaces_df.iloc[offset:offset + limit][['title', 'likes', 'url', 'category']]
170
  total_likes = spaces_df['likes'].sum()
171
 
172
- # Generate HTML content
173
  html_content = f"""
174
  <div style='margin-bottom: 20px; padding: 10px; background-color: var(--color-background-primary);
175
  border: 1px solid var(--color-border-primary); border-radius: 5px;'>
176
  <h3 style='color: var(--color-text-primary);'>Statistics:</h3>
177
- <p style='color: var(--color-text-primary);'>Page {page} of {total_pages}</p>
178
- <p style='color: var(--color-text-primary);'>Showing {offset + 1}-{min(offset + limit, total_spaces)} of {total_spaces} Spaces</p>
179
  <p style='color: var(--color-text-primary);'>Total Likes: {total_likes:,}</p>
180
  </div>
181
-
182
- <div style='display: flex; justify-content: center; gap: 10px; margin: 20px 0;'>
183
  """
184
 
185
- # Add pagination buttons
186
- if page > 1:
187
- html_content += f"<button onclick='page_change({page-1})' class='page-btn'>Previous</button>"
188
-
189
- # Add numeric page buttons
190
- for p in range(max(1, page-2), min(total_pages+1, page+3)):
191
- if p == page:
192
- html_content += f"<button onclick='page_change({p})' class='page-btn active'>{p}</button>"
193
- else:
194
- html_content += f"<button onclick='page_change({p})' class='page-btn'>{p}</button>"
195
-
196
- if page < total_pages:
197
- html_content += f"<button onclick='page_change({page+1})' class='page-btn'>Next</button>"
198
-
199
- html_content += "</div>"
200
-
201
- # Add grid container with responsive design
202
- html_content += """
203
- <div style='max-height: 800px; overflow-y: auto;'>
204
- <div style='display: grid;
205
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
206
- gap: 15px;
207
- padding: 10px;
208
- max-width: 100%;'>
209
- """
210
-
211
- # Add space cards
212
- for _, row in spaces.iterrows():
213
  html_content += f"""
214
  <div style='padding: 15px;
215
  border: 2px solid var(--color-border-primary);
@@ -219,9 +150,8 @@ def search_spaces(search_text="", category="All Categories", page=1, limit=100):
219
  display: flex;
220
  flex-direction: column;
221
  height: 100%;
222
- min-width: 0;
223
- word-wrap: break-word;'>
224
- <h3 style='margin-top: 0; margin-bottom: 10px; overflow: hidden; text-overflow: ellipsis;'>
225
  <a href='{row['url']}' target='_blank'
226
  style='color: #2196F3;
227
  text-decoration: none;
@@ -229,13 +159,13 @@ def search_spaces(search_text="", category="All Categories", page=1, limit=100):
229
  </h3>
230
  <div style='height: 2px;
231
  background: var(--color-border-primary);
232
- margin: 10px 0;'></div>
 
233
  <p style='color: var(--color-text-primary); margin: 8px 0;'>
234
  <span style='background-color: var(--color-accent-soft);
235
  padding: 2px 8px;
236
  border-radius: 12px;
237
- font-size: 0.9em;
238
- display: inline-block;'>
239
  {row['category']}
240
  </span>
241
  </p>
@@ -250,21 +180,18 @@ def search_spaces(search_text="", category="All Categories", page=1, limit=100):
250
 
251
  html_content += "</div></div>"
252
 
253
- # Add JavaScript for page navigation
254
- html_content += """
255
- <script>
256
- function page_change(page) {
257
- const pageEvent = new CustomEvent('page_change', { detail: page });
258
- document.dispatchEvent(pageEvent);
259
- }
260
- </script>
261
- """
262
-
263
- return html_content
264
 
265
  def create_app():
266
- with gr.Blocks(title="Hugging Face Spaces Explorer", theme=gr.themes.Soft()) as app:
267
- current_page = gr.State(value=1)
 
 
 
 
 
 
268
 
269
  gr.Markdown("""
270
  # 🤗 Hugging Face Spaces Explorer
@@ -275,54 +202,65 @@ def create_app():
275
  """)
276
 
277
  with gr.Row():
278
- category_dropdown = gr.Dropdown(
279
- choices=["All Categories"] + sorted(df['category'].unique()),
280
- label="Select Category",
281
- value="All Categories"
282
- )
283
- search_input = gr.Textbox(
284
- label="Search Spaces",
285
- placeholder="Enter search terms..."
286
- )
 
287
 
288
  spaces_display = gr.HTML()
 
 
 
 
 
 
 
 
 
 
 
 
 
289
 
290
- def update_spaces(search_text, category, page):
291
- return search_spaces(search_text, category, page)
 
292
 
293
- # Event handlers
 
 
 
 
 
 
294
  category_dropdown.change(
295
- fn=update_spaces,
296
- inputs=[search_input, category_dropdown, gr.State(1)],
297
- outputs=spaces_display
298
  )
299
 
300
  search_input.change(
301
- fn=update_spaces,
302
- inputs=[search_input, category_dropdown, gr.State(1)],
303
- outputs=spaces_display
304
  )
305
 
306
- # Add page change handler
307
- app.load(js="""
308
- function setupPageChangeListener() {
309
- document.addEventListener('page_change', function(e) {
310
- const page = e.detail;
311
- gradioApp().querySelector('#update_page').click();
312
- });
313
- }
314
- setupPageChangeListener();
315
- """)
316
-
317
- update_page = gr.Button(visible=False, elem_id="update_page")
318
- update_page.click(
319
- fn=update_spaces,
320
- inputs=[search_input, category_dropdown, current_page],
321
- outputs=spaces_display
322
  )
323
 
324
  return app
325
 
 
326
  # Launch the app
327
  app = create_app()
328
  app.launch(share=True)
 
111
 
112
  # ------------------------------------------------------
113
 
114
+ def search_spaces(search_text="", category="All Categories", offset=0, page_size=30):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  if category == "All Categories":
116
  spaces_df = df
117
  else:
 
120
  if search_text:
121
  spaces_df = spaces_df[spaces_df['title'].str.lower().str.contains(search_text.lower())]
122
 
 
 
123
  total_spaces = len(spaces_df)
124
+ spaces = spaces_df.nlargest(total_spaces, 'likes')[['title', 'likes', 'url', 'category']]
 
125
 
126
+ # Get category stats
 
127
  total_likes = spaces_df['likes'].sum()
128
 
129
+ # Format the results as HTML with clickable links and stats
130
  html_content = f"""
131
  <div style='margin-bottom: 20px; padding: 10px; background-color: var(--color-background-primary);
132
  border: 1px solid var(--color-border-primary); border-radius: 5px;'>
133
  <h3 style='color: var(--color-text-primary);'>Statistics:</h3>
134
+ <p style='color: var(--color-text-primary);'>Showing {min(offset + page_size, total_spaces)} of {total_spaces} Spaces</p>
 
135
  <p style='color: var(--color-text-primary);'>Total Likes: {total_likes:,}</p>
136
  </div>
137
+ <div style='max-height: 800px; overflow-y: auto;' id='spaces-container'>
138
+ <div style='display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; padding: 10px;'>
139
  """
140
 
141
+ # Only show the spaces from offset to offset + page_size
142
+ visible_spaces = spaces.iloc[offset:offset + page_size]
143
+ for _, row in visible_spaces.iterrows():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  html_content += f"""
145
  <div style='padding: 15px;
146
  border: 2px solid var(--color-border-primary);
 
150
  display: flex;
151
  flex-direction: column;
152
  height: 100%;
153
+ position: relative;'>
154
+ <h3 style='margin-top: 0; margin-bottom: 10px;'>
 
155
  <a href='{row['url']}' target='_blank'
156
  style='color: #2196F3;
157
  text-decoration: none;
 
159
  </h3>
160
  <div style='height: 2px;
161
  background: var(--color-border-primary);
162
+ margin: 10px 0;
163
+ width: 100%;'></div>
164
  <p style='color: var(--color-text-primary); margin: 8px 0;'>
165
  <span style='background-color: var(--color-accent-soft);
166
  padding: 2px 8px;
167
  border-radius: 12px;
168
+ font-size: 0.9em;'>
 
169
  {row['category']}
170
  </span>
171
  </p>
 
180
 
181
  html_content += "</div></div>"
182
 
183
+ has_more = offset + page_size < total_spaces
184
+ return html_content, has_more, total_spaces - (offset + page_size)
 
 
 
 
 
 
 
 
 
185
 
186
  def create_app():
187
+ with gr.Blocks(
188
+ title="Hugging Face Spaces Explorer",
189
+ theme=gr.themes.Soft(
190
+ primary_hue="blue",
191
+ secondary_hue="blue",
192
+ )
193
+ ) as app:
194
+ current_offset = gr.State(value=0)
195
 
196
  gr.Markdown("""
197
  # 🤗 Hugging Face Spaces Explorer
 
202
  """)
203
 
204
  with gr.Row():
205
+ with gr.Column(scale=1):
206
+ category_dropdown = gr.Dropdown(
207
+ choices=["All Categories"] + sorted(df['category'].unique()),
208
+ label="Select Category",
209
+ value="All Categories"
210
+ )
211
+ search_input = gr.Textbox(
212
+ label="Search Spaces",
213
+ placeholder="Enter search terms..."
214
+ )
215
 
216
  spaces_display = gr.HTML()
217
+ load_more_btn = gr.Button("Load More", visible=False)
218
+ remaining_text = gr.Markdown(visible=False)
219
+
220
+ def update_display(search_text, category, offset):
221
+ content, has_more, remaining = search_spaces(search_text, category, offset)
222
+ return {
223
+ spaces_display: content,
224
+ load_more_btn: gr.update(visible=has_more), # Changed from gr.Button.update
225
+ remaining_text: gr.update( # Changed from gr.Markdown.update
226
+ visible=has_more,
227
+ value=f"*{remaining} more spaces available*"
228
+ )
229
+ }
230
 
231
+ def load_more(search_text, category, offset):
232
+ new_offset = offset + 30
233
+ return update_display(search_text, category, new_offset) | {'current_offset': new_offset}
234
 
235
+ # Initial load
236
+ app.load(
237
+ fn=lambda: update_display("", "All Categories", 0),
238
+ outputs=[spaces_display, load_more_btn, remaining_text]
239
+ )
240
+
241
+ # Update display when category or search changes
242
  category_dropdown.change(
243
+ fn=lambda x, y, _: update_display(x, y, 0) | {'current_offset': 0},
244
+ inputs=[search_input, category_dropdown, current_offset],
245
+ outputs=[spaces_display, load_more_btn, remaining_text, current_offset]
246
  )
247
 
248
  search_input.change(
249
+ fn=lambda x, y, _: update_display(x, y, 0) | {'current_offset': 0},
250
+ inputs=[search_input, category_dropdown, current_offset],
251
+ outputs=[spaces_display, load_more_btn, remaining_text, current_offset]
252
  )
253
 
254
+ # Load More button handler
255
+ load_more_btn.click(
256
+ fn=load_more,
257
+ inputs=[search_input, category_dropdown, current_offset],
258
+ outputs=[spaces_display, load_more_btn, remaining_text, current_offset]
 
 
 
 
 
 
 
 
 
 
 
259
  )
260
 
261
  return app
262
 
263
+
264
  # Launch the app
265
  app = create_app()
266
  app.launch(share=True)