diff --git a/benchcoach/templates/benchcoach/card.html b/benchcoach/templates/benchcoach/card.html new file mode 100644 index 0000000..e135d70 --- /dev/null +++ b/benchcoach/templates/benchcoach/card.html @@ -0,0 +1,280 @@ +{% load static %} + + + Gamecard + + + + + + + + +
+
+
+
+ + + + + + + +
{{ event.teamsnap_event.csv_event_title }} + {% if event.home_team.name == user.profile.teamsnapsettings.managed_team.name %} + HOME + {% elif event.away_team.name == user.profile.teamsnapsettings.managed_team.name %} + AWAY + {% else %} + {% endif %} +
+ + + + + + + {% for positioning in positionings_starting %} + {% if positioning.order == 0 %} + {% else %}{% endif %} + + + + + + + + + + + + + + {% endfor %} + +
+ + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + X +
{{ positioning.order }}{{ positioning.player.last_name }}{{ positioning.player.jersey_number }}{{ positioning.position|default_if_none:'' }}
+ + + {% for line in empty_lines %} + + + + + + + + + + + + + + + {% endfor %} + +
+
+
+
+
+ + + + + + + {% for positioning in positionings %} + + + + + + + + + + + + + + + {% endfor %} + +
+ + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + X +
{{ positioning.player.jersey_number }}{{ positioning.player.last_name }}
+
+
+
+
+ \ No newline at end of file diff --git a/benchcoach/urls.py b/benchcoach/urls.py index 5af1683..8ba6ed6 100644 --- a/benchcoach/urls.py +++ b/benchcoach/urls.py @@ -11,5 +11,7 @@ urlpatterns = [ path('events//lineup', login_required(views.EventDetailView.as_view()), name="event lineup"), path('players/list/', login_required(views.PlayerListView.as_view()), name="player list"), path('teams/list/', login_required(views.TeamListView.as_view()), name="team list"), - path('venues/list/', login_required(views.VenueListView.as_view()), name="venue list") + path('venues/list/', login_required(views.VenueListView.as_view()), name="venue list"), + path('events//card', login_required(views.lineupcard), name="lineup card"), +path('events//csv', login_required(views.csv_export), name="lineup csv") ] \ No newline at end of file diff --git a/benchcoach/views.py b/benchcoach/views.py index f235a61..c8fb47b 100644 --- a/benchcoach/views.py +++ b/benchcoach/views.py @@ -1,9 +1,10 @@ -from django.shortcuts import render +from django.shortcuts import render, HttpResponse from .models import Event, Team, Player, Positioning, Venue from .forms import PositioningFormSet, TeamsnapEventForm from django.contrib import messages from django.db.models import F from django.views.generic import ListView, DetailView +import csv class BenchCoachListView(ListView): @@ -136,3 +137,102 @@ def lineup_edit(request, event_id, active_tab='details'): "formset_dhd": formset_dhd, }, ) + +def lineupcard(request, event_id): + previous_event = Event.objects.filter(id=event_id - 1).first() + + event = Event.objects.get(id=event_id) + next_event = Event.objects.get(id=event_id + 1) + players = Player.objects.prefetch_related("availability_set", "positioning_set") + + for player in players: + Positioning.objects.get_or_create(player_id=player.id, event_id=event_id) + + qs = ( + event.positioning_set.all() + .filter(player__availability__event=event_id, player__teamsnap_member__is_non_player=False) + .order_by("-player__availability__available", "player__last_name", "order") + .annotate(event_availability=F("player__availability__available")) + ) + + qs_starting = qs.filter(order__isnull=False).order_by("order") + + details = { + "Away Team": event.away_team, + "Home Team": event.home_team, + "Date": event.start.date(), + "Time": event.start.time(), + "Venue": event.venue, + } + + return render( + request, + "benchcoach/card.html", + { + "title": "Lineup", + "event": event, + "details": details, + "previous_event": previous_event, + "next_event": next_event, + "positionings": qs, + "positionings_starting": qs_starting, + "empty_lines": range(14) + }, + ) + +def csv_export(request, event_id): + response = HttpResponse( + content_type='text/csv', + headers={'Content-Disposition': f'attachment; filename=lineup-event-{event_id}.csv'}, + ) + previous_event = Event.objects.filter(id=event_id - 1).first() + + event = Event.objects.get(id=event_id) + players = Player.objects.prefetch_related("availability_set", "positioning_set") + + for player in players: + Positioning.objects.get_or_create(player_id=player.id, event_id=event_id) + + qs = ( + event.positioning_set.all() + .filter(player__availability__event=event_id, player__teamsnap_member__is_non_player=False) + .order_by("-player__availability__available", "player__last_name", "order") + .annotate(event_availability=F("player__availability__available")) + ) + + rows = [] + + rows.append(event.teamsnap_event.csv_event_title) # 2 + rows.append(event.venue.name) # 3 + [rows.append('') for i in range(3)] #4-6 + p = qs.filter(position='P').first() + rows.append(f"{p.player.last_name}, {p.player.first_name}") #7 + [rows.append('') for i in range(3)] #8-10 + for pos in ['C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF', 'DH']: #11-19 + p = qs.filter(position=pos).first() + if p: + rows.append(f"{p.player.last_name}, {p.player.first_name}") + else: + rows.append('') + ehs = qs.filter(position='EH') + if len(ehs) > 0: + p=qs.filter(position='EH')[0] + rows.append(f"{p.player.last_name}, {p.player.first_name}") # 20 + else: + rows.append('') + if len(ehs) > 1: + p=qs.filter(position='EH')[1] + rows.append(f"{p.player.last_name}, {p.player.first_name}") # 21 + else: + rows.append('') + rows.append('') #22 + p=qs.filter(position__isnull=False, order=0).first() + rows.append(f"{p.player.last_name}, {p.player.first_name}") # 23 + rows.append('') + for p in qs.filter(order__gt=0).order_by('order'): + rows.append(f"{p.player.last_name}, {p.player.first_name}") + + writer = csv.writer(response) + for row in rows: + writer.writerow([row]) + return response \ No newline at end of file diff --git a/benchcoachproject/static/css/paper.css b/benchcoachproject/static/css/paper.css new file mode 100644 index 0000000..ede1dab --- /dev/null +++ b/benchcoachproject/static/css/paper.css @@ -0,0 +1,38 @@ +@page { margin: 0 } +body { margin: 0 } +.sheet { + margin: 0; + overflow: hidden; + position: relative; + box-sizing: border-box; + page-break-after: always; +} + +/** Paper sizes **/ +body.A3 .sheet { width: 297mm; height: 419mm } +body.A3.landscape .sheet { width: 420mm; height: 296mm } +body.A4 .sheet { width: 210mm; height: 296mm } +body.A4.landscape .sheet { width: 297mm; height: 209mm } +body.A5 .sheet { width: 148mm; height: 209mm } +body.A5.landscape .sheet { width: 210mm; height: 147mm } +body.letter .sheet { width: 216mm; height: 279mm } +body.letter.landscape .sheet { width: 280mm; height: 215mm } +body.legal .sheet { width: 216mm; height: 356mm } +body.legal.landscape .sheet { width: 357mm; height: 215mm } + +/** Padding area **/ +.sheet.padding-10mm { padding: 10mm } +.sheet.padding-15mm { padding: 15mm } +.sheet.padding-20mm { padding: 20mm } +.sheet.padding-25mm { padding: 25mm } + +/** Fix for Chrome issue #273306 **/ +@media print { + body.A3.landscape { width: 420mm } + body.A3, body.A4.landscape { width: 297mm } + body.A4, body.A5.landscape { width: 210mm } + body.A5 { width: 148mm } + body.letter, body.legal { width: 216mm } + body.letter.landscape { width: 280mm } + body.legal.landscape { width: 357mm } +} diff --git a/benchcoachproject/static/css/paper.min.css b/benchcoachproject/static/css/paper.min.css new file mode 100644 index 0000000..265a771 --- /dev/null +++ b/benchcoachproject/static/css/paper.min.css @@ -0,0 +1 @@ +@page{margin:0}body{margin:0}.sheet{margin:0;overflow:hidden;position:relative;box-sizing:border-box;page-break-after:always}body.A3 .sheet{width:297mm;height:419mm}body.A3.landscape .sheet{width:420mm;height:296mm}body.A4 .sheet{width:210mm;height:296mm}body.A4.landscape .sheet{width:297mm;height:209mm}body.A5 .sheet{width:148mm;height:209mm}body.A5.landscape .sheet{width:210mm;height:147mm}body.letter .sheet{width:216mm;height:279mm}body.letter.landscape .sheet{width:280mm;height:215mm}body.legal .sheet{width:216mm;height:356mm}body.legal.landscape .sheet{width:357mm;height:215mm}.sheet.padding-10mm{padding:10mm}.sheet.padding-15mm{padding:15mm}.sheet.padding-20mm{padding:20mm}.sheet.padding-25mm{padding:25mm}@media screen{body{background:#e0e0e0}.sheet{background:#fff;box-shadow:0 .5mm 2mm rgba(0,0,0,.3);margin:5mm auto}}@media print{body.A3.landscape{width:420mm}body.A3,body.A4.landscape{width:297mm}body.A4,body.A5.landscape{width:210mm}body.A5{width:148mm}body.legal,body.letter{width:216mm}body.letter.landscape{width:280mm}body.legal.landscape{width:357mm}} \ No newline at end of file diff --git a/benchcoachproject/static/fonts/Inconsolata.ttf b/benchcoachproject/static/fonts/Inconsolata.ttf new file mode 100644 index 0000000..20251d9 Binary files /dev/null and b/benchcoachproject/static/fonts/Inconsolata.ttf differ diff --git a/benchcoachproject/static/fonts/OpenSans-Italic.ttf b/benchcoachproject/static/fonts/OpenSans-Italic.ttf new file mode 100644 index 0000000..0fea34b Binary files /dev/null and b/benchcoachproject/static/fonts/OpenSans-Italic.ttf differ diff --git a/benchcoachproject/static/fonts/OpenSans.ttf b/benchcoachproject/static/fonts/OpenSans.ttf new file mode 100644 index 0000000..51dd3c3 Binary files /dev/null and b/benchcoachproject/static/fonts/OpenSans.ttf differ