$P@D$3RV£R commited on
Commit
f50aece
·
1 Parent(s): 09628c7

Add /stats route for viewing analytics statistics

Browse files
Files changed (1) hide show
  1. app.py +150 -2
app.py CHANGED
@@ -5,7 +5,7 @@ import argparse
5
  from flask import Flask, redirect, url_for, request
6
  from flask import render_template
7
  from flask import send_file
8
- import os
9
  from datasets import load_dataset
10
  from huggingface_hub import hf_hub_download
11
  from io import BytesIO
@@ -360,6 +360,154 @@ def bye():
360
  </html>
361
  """
362
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  @app.route('/add/<temp_id>')
364
  def add(temp_id):
365
  image = request.args.get("image")
@@ -704,7 +852,7 @@ if __name__ == "__main__":
704
  app.config["FOLDER_SETS"] = []
705
  app.config["DATASET_ERROR"] = error_msg
706
  else:
707
- app.config["FOLDER_SETS"] = folder_sets
708
  app.config["DATASET_ERROR"] = None
709
  app.config["HEAD"] = 0
710
  app.config["IMAGE_SET_INDEX"] = 0
 
5
  from flask import Flask, redirect, url_for, request
6
  from flask import render_template
7
  from flask import send_file
8
+ import os
9
  from datasets import load_dataset
10
  from huggingface_hub import hf_hub_download
11
  from io import BytesIO
 
360
  </html>
361
  """
362
 
363
+ @app.route('/stats')
364
+ def stats():
365
+ """Display analytics statistics"""
366
+ stats_data = load_stats()
367
+
368
+ # Convert set to list for display
369
+ unique_count = len(stats_data['unique_visitors']) if isinstance(stats_data['unique_visitors'], set) else len(stats_data.get('unique_visitors', []))
370
+
371
+ # Sort countries by visits
372
+ sorted_countries = sorted(stats_data.get('countries', {}).items(), key=lambda x: x[1], reverse=True)
373
+
374
+ # Sort dates
375
+ sorted_dates = sorted(stats_data.get('visits_by_date', {}).items(), reverse=True)[:30] # Last 30 days
376
+
377
+ # Get top user agents
378
+ sorted_user_agents = sorted(stats_data.get('user_agents', {}).items(), key=lambda x: x[1], reverse=True)[:10]
379
+
380
+ html = f"""
381
+ <!DOCTYPE html>
382
+ <html>
383
+ <head>
384
+ <title>Analytics Statistics</title>
385
+ <meta charset="UTF-8">
386
+ <style>
387
+ body {{ font-family: Arial, sans-serif; padding: 20px; background-color: #f5f5f5; }}
388
+ .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }}
389
+ h1 {{ color: #333; border-bottom: 3px solid #007bff; padding-bottom: 10px; }}
390
+ h2 {{ color: #555; margin-top: 30px; }}
391
+ .stat-box {{ background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #007bff; }}
392
+ .stat-number {{ font-size: 36px; font-weight: bold; color: #007bff; }}
393
+ .stat-label {{ font-size: 14px; color: #666; margin-top: 5px; }}
394
+ .table {{ width: 100%; border-collapse: collapse; margin: 20px 0; }}
395
+ .table th, .table td {{ padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }}
396
+ .table th {{ background-color: #007bff; color: white; }}
397
+ .table tr:hover {{ background-color: #f5f5f5; }}
398
+ .back-link {{ display: inline-block; margin-top: 20px; padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px; }}
399
+ .back-link:hover {{ background: #0056b3; }}
400
+ .grid {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin: 20px 0; }}
401
+ </style>
402
+ </head>
403
+ <body>
404
+ <div class="container">
405
+ <h1>📊 Analytics Statistics</h1>
406
+
407
+ <div class="grid">
408
+ <div class="stat-box">
409
+ <div class="stat-number">{stats_data.get('total_visits', 0):,}</div>
410
+ <div class="stat-label">Total Visits</div>
411
+ </div>
412
+ <div class="stat-box">
413
+ <div class="stat-number">{unique_count:,}</div>
414
+ <div class="stat-label">Unique Visitors</div>
415
+ </div>
416
+ <div class="stat-box">
417
+ <div class="stat-number">{len(stats_data.get('countries', {}))}</div>
418
+ <div class="stat-label">Countries</div>
419
+ </div>
420
+ <div class="stat-box">
421
+ <div class="stat-number">{stats_data.get('first_visit', 'N/A')[:10] if stats_data.get('first_visit') else 'N/A'}</div>
422
+ <div class="stat-label">First Visit</div>
423
+ </div>
424
+ </div>
425
+
426
+ <h2>🌍 Visits by Country</h2>
427
+ <table class="table">
428
+ <thead>
429
+ <tr>
430
+ <th>Country</th>
431
+ <th>Visits</th>
432
+ <th>Percentage</th>
433
+ </tr>
434
+ </thead>
435
+ <tbody>
436
+ """
437
+
438
+ total_visits = stats_data.get('total_visits', 1)
439
+ for country, count in sorted_countries:
440
+ percentage = (count / total_visits * 100) if total_visits > 0 else 0
441
+ html += f"""
442
+ <tr>
443
+ <td>{country}</td>
444
+ <td>{count:,}</td>
445
+ <td>{percentage:.1f}%</td>
446
+ </tr>
447
+ """
448
+
449
+ html += """
450
+ </tbody>
451
+ </table>
452
+
453
+ <h2>📅 Visits by Date (Last 30 Days)</h2>
454
+ <table class="table">
455
+ <thead>
456
+ <tr>
457
+ <th>Date</th>
458
+ <th>Visits</th>
459
+ </tr>
460
+ </thead>
461
+ <tbody>
462
+ """
463
+
464
+ for date, count in sorted_dates:
465
+ html += f"""
466
+ <tr>
467
+ <td>{date}</td>
468
+ <td>{count:,}</td>
469
+ </tr>
470
+ """
471
+
472
+ html += """
473
+ </tbody>
474
+ </table>
475
+
476
+ <h2>🖥️ Top User Agents</h2>
477
+ <table class="table">
478
+ <thead>
479
+ <tr>
480
+ <th>User Agent</th>
481
+ <th>Visits</th>
482
+ </tr>
483
+ </thead>
484
+ <tbody>
485
+ """
486
+
487
+ for ua, count in sorted_user_agents:
488
+ # Truncate long user agents
489
+ ua_display = ua[:80] + '...' if len(ua) > 80 else ua
490
+ html += f"""
491
+ <tr>
492
+ <td>{ua_display}</td>
493
+ <td>{count:,}</td>
494
+ </tr>
495
+ """
496
+
497
+ html += f"""
498
+ </tbody>
499
+ </table>
500
+
501
+ <p><strong>Last Updated:</strong> {stats_data.get('last_visit', 'N/A')}</p>
502
+
503
+ <a href="/tagger" class="back-link">← Back to Tagger</a>
504
+ </div>
505
+ </body>
506
+ </html>
507
+ """
508
+
509
+ return html
510
+
511
  @app.route('/add/<temp_id>')
512
  def add(temp_id):
513
  image = request.args.get("image")
 
852
  app.config["FOLDER_SETS"] = []
853
  app.config["DATASET_ERROR"] = error_msg
854
  else:
855
+ app.config["FOLDER_SETS"] = folder_sets
856
  app.config["DATASET_ERROR"] = None
857
  app.config["HEAD"] = 0
858
  app.config["IMAGE_SET_INDEX"] = 0