add opponent views and forms
This commit is contained in:
@@ -68,6 +68,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url 'teamsnap_choose_multiple_lineups' team_id=request.user.teamsnap_preferences.managed_team_id%}?num=3">{% translate "Multi-Lineup" %}</a>
|
<a class="nav-link" href="{% url 'teamsnap_choose_multiple_lineups' team_id=request.user.teamsnap_preferences.managed_team_id%}?num=3">{% translate "Multi-Lineup" %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'teamsnap_opponents' team_id=request.user.teamsnap_preferences.managed_team_id%}">{% translate "Opponents" %}</a>
|
||||||
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import ModelForm, formset_factory
|
from django.forms import ModelForm, formset_factory
|
||||||
|
|
||||||
from .models import Preferences
|
from .models import Opponent, Preferences
|
||||||
|
|
||||||
|
|
||||||
class PreferencesForm(ModelForm):
|
class PreferencesForm(ModelForm):
|
||||||
@@ -58,10 +58,13 @@ LineupEntryFormset = formset_factory(
|
|||||||
class EventChooseForm(forms.Form):
|
class EventChooseForm(forms.Form):
|
||||||
event_id = forms.ChoiceField()
|
event_id = forms.ChoiceField()
|
||||||
|
|
||||||
# checked = forms.BooleanField(required=False)
|
|
||||||
# def __init__(self, events, *args, **kwargs):
|
class OpponentForm(forms.ModelForm):
|
||||||
# super(EventChooseForm, self).__init__(*args, **kwargs)
|
class Meta:
|
||||||
# self.fields['foo'].choices = [e.data['id'] for e in events]
|
model = Opponent
|
||||||
|
fields = "__all__"
|
||||||
|
# exclude = ["player"]
|
||||||
|
widgets = {"id": forms.HiddenInput()}
|
||||||
|
|
||||||
|
|
||||||
LineupEntryFormset = formset_factory(
|
LineupEntryFormset = formset_factory(
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
Opponent
|
Opponent
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="">{{ event.data.opponent_name }}</a>
|
<a href="{% url 'teamsnap_opponent' opponent_id=event.data.opponent_id team_id=event.data.team_id%}">{{ event.data.opponent_name }}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
9
teamsnap/templates/opponent.html
Normal file
9
teamsnap/templates/opponent.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}{{ opponent.data.name }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h4>{{ opponent.data.name }}</h4>
|
||||||
|
<form method="post" enctype="multipart/form-data">{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input type="submit" value="Save">
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
48
teamsnap/templates/opponents.html
Normal file
48
teamsnap/templates/opponents.html
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Opponents{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h4 class="display-4">Opponents</h4>
|
||||||
|
<table class="table bg-white">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Team Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Logo
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Monocolor Logo
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for ts_opponent, opponent in object_list %}
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<a class="text-decoration-none" href="{% url 'teamsnap_opponent' team_id=team_id opponent_id=opponent.id %}">
|
||||||
|
{{ ts_opponent.data.name }}
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{% if opponent.logo %}
|
||||||
|
<div class="rounded-circle bg-light p-2" style="height:64px;width:64px;">
|
||||||
|
<img class="img-fluid" src="{{ opponent.logo.url }}">
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if opponent.logo_mono %}
|
||||||
|
<div class="rounded-circle bg-dark p-2" style="height:64px;width:64px;">
|
||||||
|
<img class="img-fluid" src="{{ opponent.logo_mono.url }}">
|
||||||
|
</img>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<li>No opponents yet.</li>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock content %}
|
||||||
@@ -2,7 +2,13 @@ from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
|
|||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
||||||
from .provider import TeamsnapProvider
|
from .provider import TeamsnapProvider
|
||||||
from .views import PreferencesFormView, schedule_view, view_event
|
from .views import (
|
||||||
|
OpponentFormView,
|
||||||
|
Opponents,
|
||||||
|
PreferencesFormView,
|
||||||
|
schedule_view,
|
||||||
|
view_event,
|
||||||
|
)
|
||||||
|
|
||||||
urlpatterns = default_urlpatterns(TeamsnapProvider)
|
urlpatterns = default_urlpatterns(TeamsnapProvider)
|
||||||
|
|
||||||
@@ -17,4 +23,10 @@ urlpatterns += [
|
|||||||
),
|
),
|
||||||
path("", include("teamsnap.lineup.urls")),
|
path("", include("teamsnap.lineup.urls")),
|
||||||
path("", include("teamsnap.dashboard.urls")),
|
path("", include("teamsnap.dashboard.urls")),
|
||||||
|
path(
|
||||||
|
"<int:team_id>/opponent/<int:opponent_id>/",
|
||||||
|
OpponentFormView.as_view(),
|
||||||
|
name="teamsnap_opponent",
|
||||||
|
),
|
||||||
|
path("<int:team_id>/opponents", Opponents.as_view(), name="teamsnap_opponents"),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ from allauth.socialaccount.providers.oauth2.views import (
|
|||||||
OAuth2CallbackView,
|
OAuth2CallbackView,
|
||||||
OAuth2LoginView,
|
OAuth2LoginView,
|
||||||
)
|
)
|
||||||
from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render, reverse
|
||||||
|
from django.views.generic import ListView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
|
|
||||||
from gamechanger.models import Player as GamechangerPlayer
|
from .forms import OpponentForm, PreferencesForm
|
||||||
|
from .models import Opponent, Preferences
|
||||||
from .forms import PreferencesForm
|
|
||||||
from .models import Preferences
|
|
||||||
from .provider import TeamsnapProvider
|
from .provider import TeamsnapProvider
|
||||||
from .utils import get_teamsnap_client
|
from .utils import get_teamsnap_client
|
||||||
|
|
||||||
@@ -60,7 +59,9 @@ class PreferencesFormView(FormView):
|
|||||||
# It should return an HttpResponse.
|
# It should return an HttpResponse.
|
||||||
if form.data["user"] == str(self.request.user.id):
|
if form.data["user"] == str(self.request.user.id):
|
||||||
form.save()
|
form.save()
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
else:
|
||||||
|
return super().form_invalid(form)
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
"""
|
"""
|
||||||
@@ -180,238 +181,6 @@ def view_event(request, event_id, team_id=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def edit_lineup(request, event_ids, team_id):
|
|
||||||
import re
|
|
||||||
|
|
||||||
from pyteamsnap.api import (
|
|
||||||
Availability,
|
|
||||||
AvailabilitySummary,
|
|
||||||
Event,
|
|
||||||
EventLineup,
|
|
||||||
EventLineupEntry,
|
|
||||||
Member,
|
|
||||||
)
|
|
||||||
|
|
||||||
from teamsnap.forms import LineupEntryFormset
|
|
||||||
|
|
||||||
client = get_teamsnap_client(request)
|
|
||||||
|
|
||||||
event_ids = str(event_ids).split(",")
|
|
||||||
|
|
||||||
ts_bulkload = client.bulk_load(
|
|
||||||
team_id=team_id,
|
|
||||||
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
|
|
||||||
event__id=",".join(event_ids),
|
|
||||||
)
|
|
||||||
event_ids = [int(i) for i in event_ids]
|
|
||||||
|
|
||||||
contexts = []
|
|
||||||
for event_id in event_ids:
|
|
||||||
ts_event = [
|
|
||||||
i for i in ts_bulkload if isinstance(i, Event) and i.data["id"] == event_id
|
|
||||||
][0]
|
|
||||||
ts_availabilities = Availability.search(client, event_id=ts_event.data["id"])
|
|
||||||
ts_lineup_entries = EventLineupEntry.search(client, event_id=event_id)
|
|
||||||
|
|
||||||
ts_members = [i for i in ts_bulkload if isinstance(i, Member)]
|
|
||||||
ts_member_lookup = {m.data["id"]: m for m in ts_members}
|
|
||||||
gc_player_lookup = {
|
|
||||||
m.data["id"]: getattr(
|
|
||||||
GamechangerPlayer.objects.filter(
|
|
||||||
teamsnap_member_id=m.data["id"]
|
|
||||||
).first(),
|
|
||||||
"id",
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
for m in ts_members
|
|
||||||
}
|
|
||||||
ts_availability_lookup = {m.data["member_id"]: m for m in ts_availabilities}
|
|
||||||
ts_lineup_entries_lookup = {m.data["member_id"]: m for m in ts_lineup_entries}
|
|
||||||
|
|
||||||
members = []
|
|
||||||
|
|
||||||
for lineup_entry in ts_lineup_entries:
|
|
||||||
members.append(
|
|
||||||
{
|
|
||||||
"member": getattr(
|
|
||||||
ts_member_lookup[lineup_entry.data["member_id"]], "data"
|
|
||||||
),
|
|
||||||
"availability": getattr(
|
|
||||||
ts_availability_lookup.get(lineup_entry.data["member_id"], {}),
|
|
||||||
"data",
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
"lineup_entry": getattr(lineup_entry, "data", {}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
in_lineup_already = [m["member"] for m in members]
|
|
||||||
|
|
||||||
for member in ts_members:
|
|
||||||
if member.data not in in_lineup_already:
|
|
||||||
members.append(
|
|
||||||
{
|
|
||||||
"member": getattr(member, "data"),
|
|
||||||
"availability": getattr(
|
|
||||||
ts_availability_lookup.get(member.data["id"], {}),
|
|
||||||
"data",
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
"lineup_entry": getattr(
|
|
||||||
ts_lineup_entries_lookup.get(member.data["id"], {}),
|
|
||||||
"data",
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
members = sorted(
|
|
||||||
members,
|
|
||||||
key=lambda d: (
|
|
||||||
{None: 3, 0: 2, 2: 1, 1: 0}.get( # No Response # No # Maybe # Yes
|
|
||||||
d["availability"].get("status_code")
|
|
||||||
),
|
|
||||||
d["member"].get("last_name"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
initial = []
|
|
||||||
for member in members:
|
|
||||||
if not member["member"]["is_non_player"]:
|
|
||||||
if re.search(
|
|
||||||
r"([A-Z0-9]+)(?:\s+\[(.*)\])?",
|
|
||||||
member["lineup_entry"].get("label", ""),
|
|
||||||
):
|
|
||||||
position, position_note = re.search(
|
|
||||||
r"([A-Z0-9]+)(?:\s+\[(.*)\])?",
|
|
||||||
member["lineup_entry"].get("label", ""),
|
|
||||||
).groups()
|
|
||||||
else:
|
|
||||||
position, position_note = ("", "")
|
|
||||||
position_only = position_note == "PO"
|
|
||||||
initial.append(
|
|
||||||
{
|
|
||||||
"event_lineup_entry_id": member["lineup_entry"].get("id"),
|
|
||||||
"event_lineup_id": member["lineup_entry"].get(
|
|
||||||
"event_lineup_id"
|
|
||||||
),
|
|
||||||
"event_id": event_id,
|
|
||||||
"position_only": position_only,
|
|
||||||
"member_id": member["member"]["id"],
|
|
||||||
"sequence": member["lineup_entry"].get("sequence"),
|
|
||||||
"label": position,
|
|
||||||
"gamechanger_player_id": gc_player_lookup.get(
|
|
||||||
member["member"]["id"]
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
formset = LineupEntryFormset(initial=initial)
|
|
||||||
|
|
||||||
for form in formset:
|
|
||||||
form.member = ts_member_lookup.get(form["member_id"].initial)
|
|
||||||
form.availability = ts_availability_lookup.get(form["member_id"].initial)
|
|
||||||
|
|
||||||
formset_startinglineup = [
|
|
||||||
form
|
|
||||||
for form in formset
|
|
||||||
if form.initial.get("event_lineup_entry_id")
|
|
||||||
and not form.initial.get("position_only")
|
|
||||||
]
|
|
||||||
formset_startinglineup = sorted(
|
|
||||||
formset_startinglineup, key=lambda d: d.initial.get("sequence", 100)
|
|
||||||
)
|
|
||||||
formset_startingpositiononly = [
|
|
||||||
form
|
|
||||||
for form in formset
|
|
||||||
if form.initial.get("event_lineup_entry_id")
|
|
||||||
and form not in formset_startinglineup
|
|
||||||
]
|
|
||||||
formset_startingpositiononly = sorted(
|
|
||||||
formset_startingpositiononly, key=lambda d: d.initial.get("sequence", 100)
|
|
||||||
)
|
|
||||||
formset_bench = [
|
|
||||||
form
|
|
||||||
for form in formset
|
|
||||||
if form not in formset_startinglineup
|
|
||||||
and form not in formset_startingpositiononly
|
|
||||||
and form.availability.data["status_code"] in [2, 1]
|
|
||||||
]
|
|
||||||
formset_out = [
|
|
||||||
form
|
|
||||||
for form in formset
|
|
||||||
if form not in formset_startinglineup
|
|
||||||
and form not in formset_bench
|
|
||||||
and form not in formset_startingpositiononly
|
|
||||||
and not form.member.data["is_non_player"]
|
|
||||||
]
|
|
||||||
|
|
||||||
contexts.append(
|
|
||||||
{
|
|
||||||
"event": ts_event,
|
|
||||||
"formset": formset,
|
|
||||||
"formset_bench": formset_bench,
|
|
||||||
"formset_startinglineup": formset_startinglineup,
|
|
||||||
"formset_startingpositionalonly": formset_startingpositiononly,
|
|
||||||
"formset_out": formset_out,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return render(request, "lineup/edit.html", context={"contexts": contexts})
|
|
||||||
|
|
||||||
|
|
||||||
def submit_lineup(request, team_id, event_id):
|
|
||||||
from pyteamsnap.api import EventLineup, EventLineupEntry
|
|
||||||
|
|
||||||
from teamsnap.forms import LineupEntryFormset
|
|
||||||
|
|
||||||
client = get_teamsnap_client(request)
|
|
||||||
ts_lineup = EventLineup.search(client, event_id=event_id)
|
|
||||||
event_lineup_id = ts_lineup[0].data["id"]
|
|
||||||
if request.GET:
|
|
||||||
return HttpResponseNotAllowed()
|
|
||||||
if request.POST:
|
|
||||||
formset = LineupEntryFormset(request.POST)
|
|
||||||
if formset.is_valid():
|
|
||||||
r = []
|
|
||||||
for form in formset:
|
|
||||||
data = form.cleaned_data
|
|
||||||
if data.get("event_lineup_entry_id"):
|
|
||||||
event_lineup_entry = EventLineupEntry.get(
|
|
||||||
client, id=data.get("event_lineup_entry_id")
|
|
||||||
)
|
|
||||||
if data.get("position_only"):
|
|
||||||
data["label"] = data["label"] + " [PO]"
|
|
||||||
event_lineup_entry.data.update(data)
|
|
||||||
if not data.get("sequence") and not data.get("label"):
|
|
||||||
try:
|
|
||||||
r.append(event_lineup_entry.delete())
|
|
||||||
except Exception as e:
|
|
||||||
raise e
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
r.append(event_lineup_entry.put())
|
|
||||||
except Exception as e:
|
|
||||||
raise e
|
|
||||||
pass
|
|
||||||
elif data.get("sequence") is not None and data.get("label"):
|
|
||||||
event_lineup_entry = EventLineupEntry.new(client)
|
|
||||||
if data.get("position_only"):
|
|
||||||
data["label"] = data["label"] + " [PO]"
|
|
||||||
event_lineup_entry.data.update(data)
|
|
||||||
event_lineup_entry.data.update({"event_lineup_id": event_lineup_id})
|
|
||||||
try:
|
|
||||||
r.append(event_lineup_entry.post())
|
|
||||||
except Exception as e:
|
|
||||||
raise e
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
return HttpResponse(status=200)
|
|
||||||
return HttpResponseServerError()
|
|
||||||
|
|
||||||
|
|
||||||
def multi_lineup_choose(request, team_id):
|
def multi_lineup_choose(request, team_id):
|
||||||
from django.forms import formset_factory
|
from django.forms import formset_factory
|
||||||
from pyteamsnap.api import Event
|
from pyteamsnap.api import Event
|
||||||
@@ -464,3 +233,86 @@ def multi_lineup_choose(request, team_id):
|
|||||||
"lineup/multiple_choose.html",
|
"lineup/multiple_choose.html",
|
||||||
context={"formset": formset, "team_id": team_id},
|
context={"formset": formset, "team_id": team_id},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class OpponentFormView(FormView):
|
||||||
|
pk_url_kwarg = "opponent_id"
|
||||||
|
template_name = "opponent.html"
|
||||||
|
form_class = OpponentForm
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
team_id = self.kwargs.get("team_id")
|
||||||
|
return reverse("teamsnap_opponents", kwargs={"team_id": team_id})
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
# This method is called when valid form data has been POSTed.
|
||||||
|
# It should return an HttpResponse.
|
||||||
|
import pyteamsnap
|
||||||
|
|
||||||
|
ts_client = get_teamsnap_client(self.request)
|
||||||
|
user = pyteamsnap.api.Me(ts_client)
|
||||||
|
team_id = int(self.kwargs.get("team_id"))
|
||||||
|
opponent_id = int(self.kwargs.get("opponent_id"))
|
||||||
|
opponent = pyteamsnap.api.Opponent.get(ts_client, opponent_id)
|
||||||
|
if (
|
||||||
|
team_id in user.data["managed_team_ids"]
|
||||||
|
and opponent.data["team_id"] == team_id
|
||||||
|
):
|
||||||
|
form.save()
|
||||||
|
return super().form_valid(form)
|
||||||
|
else:
|
||||||
|
return super().form_invalid(form)
|
||||||
|
|
||||||
|
def get_form(self):
|
||||||
|
"""
|
||||||
|
Returns the initial data to use for forms on this view.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
opponent, _ = Opponent.objects.get_or_create(
|
||||||
|
id=self.kwargs.get("opponent_id")
|
||||||
|
)
|
||||||
|
form = OpponentForm(instance=opponent, **self.get_form_kwargs())
|
||||||
|
|
||||||
|
except Opponent.DoesNotExist:
|
||||||
|
form = super().get_form(self.form_class)
|
||||||
|
# form.widgets['id'] = forms.HiddenInput()
|
||||||
|
|
||||||
|
return form
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
import pyteamsnap
|
||||||
|
|
||||||
|
ts_client = get_teamsnap_client(self.request)
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
opponent = pyteamsnap.api.Opponent.get(
|
||||||
|
ts_client, self.kwargs.get("opponent_id")
|
||||||
|
)
|
||||||
|
context["opponent"] = opponent
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class Opponents(ListView):
|
||||||
|
model = Opponent
|
||||||
|
template_name = "opponents.html"
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
import pyteamsnap
|
||||||
|
|
||||||
|
ts_client = get_teamsnap_client(self.request)
|
||||||
|
team_id = self.kwargs.get("team_id")
|
||||||
|
ts_opponents = pyteamsnap.api.Opponent.search(ts_client, team_id=team_id)
|
||||||
|
ts_opponents.sort(key=lambda t: t.data.get("name"))
|
||||||
|
opponents = []
|
||||||
|
for opponent in ts_opponents:
|
||||||
|
o, _ = Opponent.objects.get_or_create(id=opponent.data["id"])
|
||||||
|
opponents.append((opponent, o))
|
||||||
|
|
||||||
|
return opponents
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
team_id = self.kwargs.get("team_id")
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["team_id"] = team_id
|
||||||
|
return context
|
||||||
|
|||||||
Reference in New Issue
Block a user