Files
SportstimeAPI/dashboard/templates/dashboard/scraper_status.html
Trey t 63acf7accb feat: add Django web app, CloudKit sync, dashboard, and game_datetime_utc export
Adds the full Django application layer on top of sportstime_parser:
- core: Sport, Team, Stadium, Game models with aliases and league structure
- scraper: orchestration engine, adapter, job management, Celery tasks
- cloudkit: CloudKit sync client, sync state tracking, sync jobs
- dashboard: staff dashboard for monitoring scrapers, sync, review queue
- notifications: email reports for scrape/sync results
- Docker setup for deployment (Dockerfile, docker-compose, entrypoint)

Game exports now use game_datetime_utc (ISO 8601 UTC) instead of
venue-local date+time strings, matching the canonical format used
by the iOS app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:04:27 -06:00

101 lines
4.0 KiB
HTML

{% extends "dashboard/base.html" %}
{% block dashboard_content %}
<div class="stat-card">
<h3>Scraper Status</h3>
<div class="stat-grid">
<div class="stat-item">
<div class="stat-value">{{ running_jobs }}</div>
<div class="stat-label">Running</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ pending_jobs }}</div>
<div class="stat-label">Pending</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ configs.count }}</div>
<div class="stat-label">Configurations</div>
</div>
</div>
</div>
<div class="stat-card">
<h3>Scraper Configurations</h3>
<div class="table-responsive">
<table class="dashboard-table">
<thead>
<tr>
<th>Sport</th>
<th>Season</th>
<th>Enabled</th>
<th>Last Run</th>
<th>Status</th>
<th>Games</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for config in configs %}
<tr>
<td><strong>{{ config.sport.short_name }}</strong></td>
<td>{{ config.sport.get_season_display }}</td>
<td>{% if config.is_enabled %}<span style="color: green;"></span>{% else %}<span style="color: #999;"></span>{% endif %}</td>
<td>{% if config.last_run %}{{ config.last_run|timesince }} ago{% else %}-{% endif %}</td>
<td>
{% if config.last_run_status %}
<span class="status-badge status-{{ config.last_run_status }}">{{ config.last_run_status|upper }}</span>
{% else %}-{% endif %}
</td>
<td>{{ config.last_run_games }}</td>
<td>
<form method="post" action="{% url 'dashboard:run_scraper' config.sport.code config.season %}" style="display: inline;">
{% csrf_token %}
<button type="submit" class="btn-action" {% if not config.is_enabled %}disabled{% endif %}>Run Now</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="stat-card">
<h3>Recent Jobs</h3>
<div class="table-responsive">
<table class="dashboard-table">
<thead>
<tr>
<th>ID</th>
<th>Sport</th>
<th>Status</th>
<th>Trigger</th>
<th>Started</th>
<th>Duration</th>
<th>Games</th>
<th>Reviews</th>
</tr>
</thead>
<tbody>
{% for job in recent_jobs %}
<tr>
<td><a href="{% url 'admin:scraper_scrapejob_change' job.id %}">{{ job.id }}</a></td>
<td>{{ job.config.sport.short_name }} {{ job.config.season }}</td>
<td><span class="status-badge status-{{ job.status }}">{{ job.status|upper }}</span></td>
<td>{{ job.triggered_by }}</td>
<td>{% if job.started_at %}{{ job.started_at|timesince }} ago{% else %}-{% endif %}</td>
<td>{{ job.duration_display }}</td>
<td>
{% if job.games_found %}
{{ job.games_found }} ({{ job.games_new }} new, {{ job.games_updated }} upd)
{% else %}-{% endif %}
</td>
<td>{% if job.review_items_created %}{{ job.review_items_created }}{% else %}-{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}