cduss commited on
Commit
af8590f
·
verified ·
1 Parent(s): 871df0d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +155 -18
index.html CHANGED
@@ -203,6 +203,29 @@
203
  overflow: hidden;
204
  }
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  .app-stats {
207
  display: flex;
208
  justify-content: space-between;
@@ -260,6 +283,20 @@
260
  margin: 20px 0;
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  @media (max-width: 768px) {
264
  .header h1 {
265
  font-size: 2rem;
@@ -287,12 +324,12 @@
287
  <div class="container">
288
  <div class="header">
289
  <h1>🤖 Reachy Mini Spaces</h1>
290
- <p>Discover amazing AI-powered applications and demos</p>
291
  </div>
292
 
293
  <div class="controls">
294
  <div class="search-box">
295
- <input type="text" id="searchInput" placeholder="Search spaces..." />
296
  </div>
297
  <div class="sort-controls">
298
  <button class="sort-btn active" data-sort="likes">❤️ Likes</button>
@@ -302,7 +339,7 @@
302
  </div>
303
 
304
  <div class="stats" id="stats">
305
- <div class="loading">Loading Reachy Mini spaces...</div>
306
  </div>
307
 
308
  <div class="grid" id="spacesGrid">
@@ -316,6 +353,7 @@
316
  this.filteredSpaces = [];
317
  this.currentSort = 'likes';
318
  this.searchTerm = '';
 
319
  this.init();
320
  }
321
 
@@ -327,24 +365,81 @@
327
 
328
  async loadSpaces() {
329
  try {
330
- const response = await fetch('https://huggingface.co/api/spaces?search=reachy-mini&sort=likes&direction=-1&limit=50');
 
 
 
 
 
 
331
  const data = await response.json();
332
 
333
- this.spaces = data.map(space => ({
 
 
 
 
 
334
  id: space.id,
335
  title: space.id.split('/').pop().replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
336
  author: space.author,
337
- description: space.cardData?.short_description || 'No description available',
338
  likes: space.likes || 0,
339
  created: new Date(space.createdAt).getTime(),
340
  url: `https://huggingface.co/spaces/${space.id}`,
341
- tags: space.tags || []
 
342
  }));
343
 
 
 
 
 
 
344
  this.filteredSpaces = [...this.spaces];
345
  this.updateStats();
346
  } catch (error) {
347
  console.error('Error loading spaces:', error);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  this.showError();
349
  }
350
  }
@@ -373,7 +468,8 @@
373
  this.filteredSpaces = this.spaces.filter(space =>
374
  space.title.toLowerCase().includes(this.searchTerm) ||
375
  space.author.toLowerCase().includes(this.searchTerm) ||
376
- space.description.toLowerCase().includes(this.searchTerm)
 
377
  );
378
  this.sortSpaces();
379
  }
@@ -397,14 +493,44 @@
397
  const statsEl = document.getElementById('stats');
398
  const total = this.spaces.length;
399
  const totalLikes = this.spaces.reduce((sum, space) => sum + space.likes, 0);
400
- statsEl.innerHTML = `Found ${total} spaces with ${totalLikes.toLocaleString()} total likes`;
 
 
 
 
 
 
 
 
401
  }
402
 
403
  renderSpaces() {
404
  const grid = document.getElementById('spacesGrid');
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  if (this.filteredSpaces.length === 0) {
407
- grid.innerHTML = '<div class="error">No spaces found matching your criteria</div>';
 
 
 
 
 
 
408
  return;
409
  }
410
 
@@ -412,7 +538,7 @@
412
  <div class="app-card" onclick="window.open('${space.url}', '_blank')">
413
  <div class="app-header">
414
  <div class="app-icon">
415
- ${space.title.charAt(0)}
416
  </div>
417
  <div class="app-info">
418
  <div class="app-title">${space.title}</div>
@@ -420,6 +546,14 @@
420
  </div>
421
  </div>
422
  <div class="app-description">${space.description}</div>
 
 
 
 
 
 
 
 
423
  <div class="app-stats">
424
  <div class="stat-item">
425
  <span class="stat-icon">❤️</span>
@@ -434,6 +568,14 @@
434
  `).join('');
435
  }
436
 
 
 
 
 
 
 
 
 
437
  formatDate(timestamp) {
438
  const date = new Date(timestamp);
439
  const now = new Date();
@@ -454,16 +596,11 @@
454
  grid.innerHTML = `
455
  <div class="error">
456
  <h3>Unable to load Hugging Face Spaces</h3>
457
- <p>This might be due to CORS restrictions. The design is fully functional - you can see how it would work with real data!</p>
458
- <p>In a production environment, you'd use a backend API or proxy to fetch the data.</p>
459
  </div>
460
  `;
461
-
462
- // Show demo data instead
463
- // setTimeout(() => this.loadDemoData(), 2000);
464
  }
465
-
466
-
467
  }
468
 
469
  // Initialize the app
 
203
  overflow: hidden;
204
  }
205
 
206
+ .app-tags {
207
+ display: flex;
208
+ flex-wrap: wrap;
209
+ gap: 6px;
210
+ margin-bottom: 15px;
211
+ }
212
+
213
+ .tag {
214
+ background: rgba(102, 126, 234, 0.1);
215
+ color: #667eea;
216
+ padding: 4px 8px;
217
+ border-radius: 12px;
218
+ font-size: 0.75rem;
219
+ font-weight: 500;
220
+ border: 1px solid rgba(102, 126, 234, 0.2);
221
+ }
222
+
223
+ .tag.primary {
224
+ background: rgba(102, 126, 234, 0.2);
225
+ color: #4c5eb8;
226
+ border-color: rgba(102, 126, 234, 0.4);
227
+ }
228
+
229
  .app-stats {
230
  display: flex;
231
  justify-content: space-between;
 
283
  margin: 20px 0;
284
  }
285
 
286
+ .no-results {
287
+ text-align: center;
288
+ color: white;
289
+ background: rgba(255, 255, 255, 0.1);
290
+ padding: 40px;
291
+ border-radius: 15px;
292
+ margin: 20px 0;
293
+ }
294
+
295
+ .no-results h3 {
296
+ margin-bottom: 15px;
297
+ font-size: 1.5rem;
298
+ }
299
+
300
  @media (max-width: 768px) {
301
  .header h1 {
302
  font-size: 2rem;
 
324
  <div class="container">
325
  <div class="header">
326
  <h1>🤖 Reachy Mini Spaces</h1>
327
+ <p>Discover AI-powered applications with the reachy_mini tag</p>
328
  </div>
329
 
330
  <div class="controls">
331
  <div class="search-box">
332
+ <input type="text" id="searchInput" placeholder="Search within reachy_mini spaces..." />
333
  </div>
334
  <div class="sort-controls">
335
  <button class="sort-btn active" data-sort="likes">❤️ Likes</button>
 
339
  </div>
340
 
341
  <div class="stats" id="stats">
342
+ <div class="loading">Loading spaces with reachy_mini tag...</div>
343
  </div>
344
 
345
  <div class="grid" id="spacesGrid">
 
353
  this.filteredSpaces = [];
354
  this.currentSort = 'likes';
355
  this.searchTerm = '';
356
+ this.targetTag = 'reachy_mini';
357
  this.init();
358
  }
359
 
 
365
 
366
  async loadSpaces() {
367
  try {
368
+ // First, try to get spaces by tag
369
+ const response = await fetch(`https://huggingface.co/api/spaces?tags=${this.targetTag}&sort=likes&direction=-1&limit=100`);
370
+
371
+ if (!response.ok) {
372
+ throw new Error(`HTTP error! status: ${response.status}`);
373
+ }
374
+
375
  const data = await response.json();
376
 
377
+ // Filter spaces that actually have the reachy_mini tag
378
+ const reachyMiniSpaces = data.filter(space =>
379
+ space.tags && space.tags.includes(this.targetTag)
380
+ );
381
+
382
+ this.spaces = reachyMiniSpaces.map(space => ({
383
  id: space.id,
384
  title: space.id.split('/').pop().replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
385
  author: space.author,
386
+ description: space.cardData?.short_description || space.cardData?.description || 'No description available',
387
  likes: space.likes || 0,
388
  created: new Date(space.createdAt).getTime(),
389
  url: `https://huggingface.co/spaces/${space.id}`,
390
+ tags: space.tags || [],
391
+ downloads: space.downloads || 0
392
  }));
393
 
394
+ // If no spaces found with tag, try alternative search
395
+ if (this.spaces.length === 0) {
396
+ await this.fallbackSearch();
397
+ }
398
+
399
  this.filteredSpaces = [...this.spaces];
400
  this.updateStats();
401
  } catch (error) {
402
  console.error('Error loading spaces:', error);
403
+ await this.fallbackSearch();
404
+ }
405
+ }
406
+
407
+ async fallbackSearch() {
408
+ try {
409
+ console.log('Trying fallback search...');
410
+ // Fallback: search by text in case tag search doesn't work
411
+ const response = await fetch('https://huggingface.co/api/spaces?search=reachy&sort=likes&direction=-1&limit=100');
412
+
413
+ if (!response.ok) {
414
+ throw new Error(`HTTP error! status: ${response.status}`);
415
+ }
416
+
417
+ const data = await response.json();
418
+
419
+ // Filter for spaces that contain "reachy" or "mini" in name/description
420
+ const reachySpaces = data.filter(space => {
421
+ const name = space.id.toLowerCase();
422
+ const description = (space.cardData?.short_description || space.cardData?.description || '').toLowerCase();
423
+ return name.includes('reachy') || name.includes('mini') ||
424
+ description.includes('reachy') || description.includes('mini');
425
+ });
426
+
427
+ this.spaces = reachySpaces.map(space => ({
428
+ id: space.id,
429
+ title: space.id.split('/').pop().replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()),
430
+ author: space.author,
431
+ description: space.cardData?.short_description || space.cardData?.description || 'No description available',
432
+ likes: space.likes || 0,
433
+ created: new Date(space.createdAt).getTime(),
434
+ url: `https://huggingface.co/spaces/${space.id}`,
435
+ tags: space.tags || [],
436
+ downloads: space.downloads || 0
437
+ }));
438
+
439
+ this.filteredSpaces = [...this.spaces];
440
+ this.updateStats();
441
+ } catch (error) {
442
+ console.error('Fallback search also failed:', error);
443
  this.showError();
444
  }
445
  }
 
468
  this.filteredSpaces = this.spaces.filter(space =>
469
  space.title.toLowerCase().includes(this.searchTerm) ||
470
  space.author.toLowerCase().includes(this.searchTerm) ||
471
+ space.description.toLowerCase().includes(this.searchTerm) ||
472
+ space.tags.some(tag => tag.toLowerCase().includes(this.searchTerm))
473
  );
474
  this.sortSpaces();
475
  }
 
493
  const statsEl = document.getElementById('stats');
494
  const total = this.spaces.length;
495
  const totalLikes = this.spaces.reduce((sum, space) => sum + space.likes, 0);
496
+ const filtered = this.filteredSpaces.length;
497
+
498
+ if (total === 0) {
499
+ statsEl.innerHTML = `No spaces found with "${this.targetTag}" tag`;
500
+ } else if (filtered === total) {
501
+ statsEl.innerHTML = `Found ${total} spaces with "${this.targetTag}" tag (${totalLikes.toLocaleString()} total likes)`;
502
+ } else {
503
+ statsEl.innerHTML = `Showing ${filtered} of ${total} spaces with "${this.targetTag}" tag`;
504
+ }
505
  }
506
 
507
  renderSpaces() {
508
  const grid = document.getElementById('spacesGrid');
509
 
510
+ if (this.spaces.length === 0) {
511
+ grid.innerHTML = `
512
+ <div class="no-results">
513
+ <h3>🔍 No Spaces Found</h3>
514
+ <p>No spaces were found with the "reachy_mini" tag.</p>
515
+ <p>This might be because:</p>
516
+ <ul style="text-align: left; margin-top: 15px;">
517
+ <li>The tag doesn't exist yet on Hugging Face</li>
518
+ <li>Spaces with this tag haven't been published</li>
519
+ <li>There might be API restrictions</li>
520
+ </ul>
521
+ </div>
522
+ `;
523
+ return;
524
+ }
525
+
526
  if (this.filteredSpaces.length === 0) {
527
+ grid.innerHTML = `
528
+ <div class="no-results">
529
+ <h3>🔍 No Results</h3>
530
+ <p>No spaces match your search criteria.</p>
531
+ <p>Try adjusting your search terms or clearing the search box.</p>
532
+ </div>
533
+ `;
534
  return;
535
  }
536
 
 
538
  <div class="app-card" onclick="window.open('${space.url}', '_blank')">
539
  <div class="app-header">
540
  <div class="app-icon">
541
+ ${this.getSpaceIcon(space)}
542
  </div>
543
  <div class="app-info">
544
  <div class="app-title">${space.title}</div>
 
546
  </div>
547
  </div>
548
  <div class="app-description">${space.description}</div>
549
+ ${space.tags.length > 0 ? `
550
+ <div class="app-tags">
551
+ ${space.tags.slice(0, 5).map(tag => `
552
+ <span class="tag ${tag === this.targetTag ? 'primary' : ''}">${tag}</span>
553
+ `).join('')}
554
+ ${space.tags.length > 5 ? `<span class="tag">+${space.tags.length - 5}</span>` : ''}
555
+ </div>
556
+ ` : ''}
557
  <div class="app-stats">
558
  <div class="stat-item">
559
  <span class="stat-icon">❤️</span>
 
568
  `).join('');
569
  }
570
 
571
+ getSpaceIcon(space) {
572
+ // Return robot emoji for reachy-related spaces, otherwise first letter
573
+ if (space.title.toLowerCase().includes('reachy') || space.tags.includes('reachy_mini')) {
574
+ return '🤖';
575
+ }
576
+ return space.title.charAt(0).toUpperCase();
577
+ }
578
+
579
  formatDate(timestamp) {
580
  const date = new Date(timestamp);
581
  const now = new Date();
 
596
  grid.innerHTML = `
597
  <div class="error">
598
  <h3>Unable to load Hugging Face Spaces</h3>
599
+ <p>This might be due to CORS restrictions or API limitations.</p>
600
+ <p>The dashboard is fully functional - in a production environment, you'd use a backend API or proxy to fetch the data.</p>
601
  </div>
602
  `;
 
 
 
603
  }
 
 
604
  }
605
 
606
  // Initialize the app