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>
177 lines
9.1 KiB
HTML
177 lines
9.1 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{% block content %}
|
|
<div class="page-header">
|
|
<h2>Export Data</h2>
|
|
</div>
|
|
|
|
<!-- Overview Stats -->
|
|
<div class="stat-grid mb-2">
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{ counts.teams }}</div>
|
|
<div class="stat-label">Teams</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{ counts.stadiums }}</div>
|
|
<div class="stat-label">Stadiums</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{ counts.games|floatformat:0 }}</div>
|
|
<div class="stat-label">Games</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{ counts.team_aliases }}</div>
|
|
<div class="stat-label">Team Aliases</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value">{{ counts.stadium_aliases }}</div>
|
|
<div class="stat-label">Stadium Aliases</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid-2">
|
|
<!-- Export Options -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Export Options</h3>
|
|
</div>
|
|
<form id="exportForm" method="get" action="{% url 'dashboard:export_download' %}">
|
|
<div style="margin-bottom: 1.5rem;">
|
|
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Data Types</label>
|
|
<div style="display: grid; gap: 0.5rem;">
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="sports" checked>
|
|
<span>Sports</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.sports }} sports)</span>
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="league_structure" checked>
|
|
<span>League Structure</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.conferences }} conferences, {{ counts.divisions }} divisions)</span>
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="teams" checked>
|
|
<span>Teams</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.teams }} teams)</span>
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="stadiums" checked>
|
|
<span>Stadiums</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.stadiums }} stadiums)</span>
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="games" checked>
|
|
<span>Games</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.games }} games)</span>
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="team_aliases" checked>
|
|
<span>Team Aliases</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.team_aliases }} aliases)</span>
|
|
</label>
|
|
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
<input type="checkbox" name="type" value="stadium_aliases" checked>
|
|
<span>Stadium Aliases</span>
|
|
<span class="text-muted" style="font-size: 0.85rem;">({{ counts.stadium_aliases }} aliases)</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 1.5rem;">
|
|
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Filter by Sport</label>
|
|
<select name="sport" style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 6px;">
|
|
<option value="">All Sports</option>
|
|
{% for sport in sports %}
|
|
<option value="{{ sport.code }}">{{ sport.short_name }} - {{ sport.name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<div style="margin-bottom: 1.5rem;">
|
|
<label style="display: block; font-weight: 600; margin-bottom: 0.5rem;">Filter Games by Year</label>
|
|
<select name="year" style="width: 100%; padding: 0.5rem; border: 1px solid #ddd; border-radius: 6px;">
|
|
<option value="">All Years</option>
|
|
{% for year in years %}
|
|
<option value="{{ year }}">{{ year }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<span class="text-muted" style="font-size: 0.85rem; display: block; margin-top: 0.25rem;">All games played in this calendar year, regardless of season</span>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary" style="width: 100%; padding: 0.75rem;">
|
|
Download Export
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Export Files Info -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3>Output Files</h3>
|
|
</div>
|
|
<div style="display: grid; gap: 1rem;">
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">sports_canonical.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
Sport metadata: display names, SF Symbol icons, brand colors, and season month ranges.
|
|
</p>
|
|
</div>
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">league_structure.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
League hierarchy: sports as leagues, conferences, and divisions with parent_id references.
|
|
</p>
|
|
</div>
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">teams_canonical.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
Teams with canonical IDs, abbreviations, stadium references, and conference/division IDs.
|
|
</p>
|
|
</div>
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">stadiums_canonical.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
Stadiums with coordinates, capacity, timezone, and primary team abbreviations.
|
|
</p>
|
|
</div>
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">games_canonical.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
Games with local date/time (converted from UTC), team names, abbreviations, and canonical IDs.
|
|
</p>
|
|
</div>
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">team_aliases.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
Historical team names and abbreviations with validity date ranges.
|
|
</p>
|
|
</div>
|
|
<div style="padding: 1rem; background: #f8f9fa; border-radius: 8px;">
|
|
<strong style="color: #1a1a2e;">stadium_aliases.json</strong>
|
|
<p class="text-muted mb-0" style="font-size: 0.85rem; margin-top: 0.25rem;">
|
|
Stadium name aliases (e.g., former naming rights) with validity dates.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Export Buttons -->
|
|
<div class="card mt-2">
|
|
<div class="card-header">
|
|
<h3>Quick Export</h3>
|
|
</div>
|
|
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
|
<a href="{% url 'dashboard:export_download' %}?type=sports&type=league_structure&type=teams&type=stadiums&type=games&type=team_aliases&type=stadium_aliases" class="btn btn-success">
|
|
Export All Data
|
|
</a>
|
|
<a href="{% url 'dashboard:export_download' %}?type=sports&type=league_structure&type=teams&type=stadiums" class="btn btn-primary">
|
|
Export Structure Only (No Games)
|
|
</a>
|
|
<a href="{% url 'dashboard:export_download' %}?type=games" class="btn btn-secondary">
|
|
Export Games Only
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|