implement lineup send to gamechanger

This commit is contained in:
2022-06-08 14:08:33 -05:00
parent 50c9b70546
commit f788fb9932
21 changed files with 409 additions and 82 deletions

View File

@@ -32,3 +32,9 @@
vertical-align: middle;
white-space: nowrap;
}
.btn-gamechanger {
color: #fff;
border-color: #1b73bc;
background-color: #1b73bc;
}

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 741.9 69.6" style="enable-background:new 0 0 741.9 69.6;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
.st1{filter:url(#Adobe_OpacityMaskFilter);}
.st2{mask:url(#mask-2_00000067194953457310049560000009970419005216943005_);fill-rule:evenodd;clip-rule:evenodd;fill:#00F092;}
</style>
<g id="Logo-Presentation">
<g id="Slide-1-Copy-23" transform="translate(-194.000000, -546.000000)">
<g id="Group-10" transform="translate(194.000000, 546.500000)">
<path id="Fill-1" class="st0" d="M497.6,38.9h-9.4l7.9-15l8,15H497.6z M492.2,15.6l-19.8,37.5h8.3l3.6-6.7h23.8l3.6,6.7h8.3
l-19.9-37.5H492.2L492.2,15.6z"/>
<polyline id="Fill-2" class="st0" points="557.8,42.2 557.7,42.1 533.8,15.6 525.3,15.6 525.3,53.1 532.7,53.1 532.7,25.1
532.8,25.2 557.9,53.1 565.2,53.1 565.2,15.6 557.8,15.6 557.8,42.2 "/>
<path id="Fill-3" class="st0" d="M702.5,33.6h-18.7V23h18.7c1.4,0,2.7,0.6,3.7,1.6l0,0c1,1,1.5,2.3,1.5,3.7s-0.5,2.7-1.5,3.7
C705.2,33.1,703.9,33.6,702.5,33.6z M706.9,40.3l0.5-0.2c2.3-1,4.2-2.6,5.5-4.6c1.4-2.1,2.2-4.6,2.2-7.1c0-3.4-1.3-6.6-3.7-9
c-2.4-2.5-5.5-3.8-8.9-3.8h-26v37.5h7.3V41h13.9l0,0l10.5,12.1h9.8L706.9,40.3L706.9,40.3z"/>
<polyline id="Fill-4" class="st0" points="459.8,30.6 434.9,30.6 434.9,15.6 427.5,15.6 427.5,53.1 434.9,53.1 434.9,38.1
459.8,38.1 459.8,53.1 467.1,53.1 467.1,15.6 459.8,15.6 459.8,30.6 "/>
<polyline id="Fill-5" class="st0" points="318.6,15.6 315.1,15.6 303.2,42.8 291.2,15.6 287.7,15.6 287.7,15.6 280.7,15.6
280.7,53.1 288.2,53.1 288.2,25.7 300.2,53.1 306.1,53.1 318.2,25.6 318.2,53.1 325.6,53.1 325.6,15.6 318.6,15.6 318.6,15.6
"/>
<g id="Group-9" transform="translate(0.000000, 0.008595)">
<g id="Clip-7">
</g>
<path id="Fill-6" class="st0" d="M252.6,38.9L252.6,38.9h-9.4l7.9-15l8,15H252.6z M247.2,15.6l-19.8,37.5h8.3l3.6-6.7h23.8
l3.6,6.7h8.3l-19.9-37.5H247.2L247.2,15.6z"/>
<path id="Fill-8" class="st0" d="M199.2,36.9v0.4H218v0.1c-1.4,4.8-5.8,8.2-10.8,8.2h-10c-6.1,0-11.1-5-11.2-11.1
c-0.1-3,1.1-5.9,3.2-8c2.2-2.2,5.2-3.5,8.2-3.5h9.1c4,0,7.3-3,7.8-7v-0.4h-17.2c-5,0-9.7,2-13.3,5.6c-3.5,3.6-5.4,8.4-5.3,13.4
c0.2,10.2,8.6,18.5,18.9,18.5h9.5h0.1c10.1-0.1,18.5-8.4,18.7-18.5c0-0.1,0-0.2,0-0.2c0-0.1,0-0.1,0-0.2v-0.1l0,0v-4.2H207
C203,29.9,199.6,32.9,199.2,36.9"/>
</g>
<path id="Fill-10" class="st0" d="M594.4,36.9v0.4h18.8v0.1c-1.4,4.8-5.8,8.2-10.8,8.2h-10c-6.1,0-11.1-5-11.2-11.1
c-0.1-3,1.1-5.9,3.2-8c2.2-2.2,5.2-3.5,8.2-3.5h9.1c4,0,7.3-3,7.8-7v-0.4h-17.1c-5,0-9.7,2-13.3,5.6c-3.5,3.6-5.4,8.4-5.4,13.4
c0.2,10.2,8.6,18.5,18.9,18.5h9.5h0.1c10.2-0.1,18.6-8.4,18.7-18.4c0-0.1,0-0.2,0-0.2c0-0.1,0-0.1,0-0.2v-0.1l0,0V30h-18.7
C598.1,30,594.8,33,594.4,36.9"/>
<path id="Fill-11" class="st0" d="M398,23h13.7c4,0,7.3-3,7.8-7v-0.4H398c-5,0-9.7,2-13.3,5.6c-3.5,3.6-5.4,8.4-5.4,13.4
c0.2,10.2,8.6,18.5,18.9,18.5h13.4c4,0,7.3-3,7.8-7v-0.4h-21.3c-3.1,0-6.1-1.3-8.2-3.5s-3.3-5-3.2-8C386.9,28,391.9,23,398,23"/>
<path id="Fill-12" class="st0" d="M367.1,23c4,0,7.3-3,7.7-7v-0.4h-38.6v37.5h30.9c4,0,7.3-3,7.7-7v-0.4h-31.3v-7.6h14
c3.8,0,7-3.1,7-7v-0.5h-20.9V23H367.1"/>
<path id="Fill-13" class="st0" d="M660.4,23c4,0,7.3-3,7.7-7v-0.4h-38.6v37.5h30.9c4,0,7.3-3,7.7-7v-0.4h-31.3v-7.6h13.9
c3.8,0,7-3.1,7-7v-0.5h-20.9V23H660.4"/>
<polyline id="Fill-14" class="st0" points="728.9,53.1 727.5,53.1 727.5,45.6 724.9,45.6 724.9,44.3 731.4,44.3 731.4,45.6
728.9,45.6 728.9,53.1 "/>
<path id="Fill-15" class="st0" d="M736.8,53.1l-2.5-7.2l0,0c0,1.1,0.1,2.1,0.1,3.1v4.2h-1.2v-8.7h1.9l2.4,6.9l0,0l2.5-6.9h1.9
v8.7h-1.4v-4.3c0-0.4,0-1,0-1.7s0-1.1,0-1.2l0,0l-2.6,7.2H736.8"/>
</g>
</g>
</g>
<g id="Logo-Presentation_00000113341718855537428600000001450668188223146168_">
<g id="Slide-1-Copy-23_00000093891632931889047450000011681990669367062677_" transform="translate(-551.000000, -849.000000)">
<g id="DSG_GameChanger_Logomark-Copy-7" transform="translate(551.000000, 849.000000)">
<g id="Clip-2">
</g>
<defs>
<filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="0" y="0" width="142.9" height="69.6">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"/>
</filter>
</defs>
<mask maskUnits="userSpaceOnUse" x="0" y="0" width="142.9" height="69.6" id="mask-2_00000067194953457310049560000009970419005216943005_">
<g class="st1">
<polygon id="path-1_00000010310054758688279420000011862642130963442847_" class="st0" points="0,0 142.9,0 142.9,69.6 0,69.6
"/>
</g>
</mask>
<path id="Fill-1_00000052789438335131278620000014152493238395228080_" class="st2" d="M104.9,55.5c-2.9,0-5.8-0.7-8.4-1.9
c-2.5-1.2-4.8-3-6.7-5.2c-1.8-2.2-3.2-4.8-4-7.5c-0.8-2.9-1-6-0.6-9c1.2-8.3,7.4-15.2,15.5-17.2c0.5-0.1,3.2-0.6,6.7-0.6l22.4,0
c0.1,0,3.1,0,5.8-1.3c4.4-2.5,7.2-7.3,7.2-12.4V0h-38C89,0,75.3,10.9,71.5,26.5c0,0.1,0,0.1,0,0.2l0,0.1H50.7
c-7.5,0-13.7,6-14,13.6l0,0.5h33l0,0c0,0.2-0.1,0.5-0.2,0.8c-2.3,6.8-8.1,12.1-15.1,13.9c0,0-2.9,0.7-6.8,0.6H37
c-3.6,0-6.2-0.5-6.7-0.6c-9.1-2.3-15.6-10.4-15.7-19.8c0-1.1,0-2.4,0.2-3.7c1.2-8.3,7.4-15.3,15.5-17.3c0.5-0.1,3.2-0.6,6.7-0.6
l11.4,0c0.2,0,4,0,7-1.9c3.9-2.7,6.2-7.1,6.2-11.8V0H34.4C15.7,0,0.3,15.3,0,34.2c-0.2,9.2,3.3,18,9.9,24.7
c6.6,6.8,15.8,10.7,25.1,10.7h15.7c10.6,0,20.7-5.1,27.2-13.6c6.7,8.5,16.9,13.6,27.6,13.6h23.4c7.5,0,13.7-6,14-13.6l0-0.5
H104.9"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -85,6 +85,9 @@
<li class="dropdown-item">
<a class="nav-link" href="{% url 'gamechanger_preferences' %}">{% translate "GameChanger Preferences" %}</a>
</li>
<li class="dropdown-item">
<a class="nav-link" href="{% url 'gamechanger_import_roster' %}">{% translate "GameChanger Import Roster" %}</a>
</li>
<li><hr class="dropdown-divider"></li>
<li class="dropdown-item">
<a class="nav-link" href="{% url 'account_logout' %}">{% translate "Sign Out" %}</a>

View File

@@ -272,5 +272,5 @@ SOCIALACCOUNT_FORMS = {"signup": "benchcoach.users.forms.UserSocialSignupForm"}
# Your stuff...
# ------------------------------------------------------------------------------
INSTALLED_APPS += ["teamsnap", "instagen"]
INSTALLED_APPS += ["teamsnap", "instagen", "gamechanger"]
SOCIALACCOUNT_PROVIDERS = {"teamsnap": {"SCOPE": ["read", "write"]}}

View File

@@ -1,6 +1,8 @@
from django.contrib import admin
from .models import Account, Preferences
from .models import Account, Player, Preferences
# Register your models here.
admin.site.register(Account)
admin.site.register(Preferences)
admin.site.register(Player)

View File

@@ -1,7 +1,8 @@
from django import forms
from django.forms import ModelForm, formset_factory
from .models import Preferences, Account, Player
from .models import Account, Player, Preferences
class PreferencesForm(ModelForm):
class Meta:
@@ -13,6 +14,7 @@ class PreferencesForm(ModelForm):
}
labels = {"managed_team_id": "Selected Team"}
class AccountForm(ModelForm):
class Meta:
model = Account
@@ -20,16 +22,24 @@ class AccountForm(ModelForm):
widgets = {
"user": forms.HiddenInput(),
"email": forms.EmailInput(),
"password": forms.PasswordInput()
"password": forms.PasswordInput(),
}
class PlayerForm(ModelForm):
gamechanger_name = forms.Field()
teamsnap_name = forms.Field()
gamechanger_id = forms.Field()
fname = forms.Field()
lname = forms.Field()
class Meta:
model = Player
fields = ['id', 'teamsnap_member_id']
fields = ["id", "teamsnap_member_id"]
widgets = {
"teamsnap_member_id": forms.Select(
choices=(), attrs={"class": "form-control"}
),
}
PlayerFormSet = formset_factory(PlayerForm, can_delete=True, extra=0)

View File

@@ -0,0 +1,22 @@
# Generated by Django 3.2.13 on 2022-06-08 12:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gamechanger', '0002_auto_20220607_1259'),
]
operations = [
migrations.CreateModel(
name='Player',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('teamsnap_member_id', models.IntegerField()),
('fname', models.CharField(max_length=30)),
('lname', models.CharField(max_length=30)),
],
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2.13 on 2022-06-08 12:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gamechanger', '0003_player'),
]
operations = [
migrations.AlterField(
model_name='player',
name='id',
field=models.CharField(max_length=30, primary_key=True, serialize=False),
),
]

View File

@@ -1,20 +1,36 @@
from django import forms
from django.db import models
from django.db.models import CharField, EmailField
from benchcoach.users.models import User
# Create your models here.
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="gamechanger_account")
user = models.OneToOneField(
User, on_delete=models.CASCADE, related_name="gamechanger_account"
)
email = EmailField()
password = CharField(max_length=255)
class Preferences(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="gamechanger_preferences")
user = models.OneToOneField(
User, on_delete=models.CASCADE, related_name="gamechanger_preferences"
)
season_id = CharField(max_length=255)
team_id = CharField(max_length=255)
class Meta:
verbose_name_plural = "preferences"
class Player(models.Model):
id = models.AutoField(primary_key=True)
id = models.CharField(primary_key=True, max_length=30)
teamsnap_member_id = models.IntegerField()
fname = CharField(max_length=30)
lname = CharField(max_length=30)
widgets = {
"teamsnap_member_id": forms.Select(choices=(), attrs={"class": "form-control"}),
}

View File

@@ -5,7 +5,7 @@
{# {{ player.fname }} {{ player.lname }}#}
{# </li>#}
{# {% endfor %}#}
<form method="post" action='{% url 'gamechanger_save' %}' >
<form method="post" action='{% url 'gamechanger_import_roster' %}' >
{{ formset.management_form }}
{% csrf_token %}
<table>
@@ -23,16 +23,20 @@
{% for form in formset %}
<tr>
<td>
{{ form.gamechanger_name }}
{{ form.gamechanger_name.value }}
</td>
<td>
{{ form.teamsnap_name }}
{{ form.teamsnap_member_id }}
</td>
<td>
{{ form.DELETE }}
</td>
{{ form.gamechanger_id.as_hidden }}
{{ form.gamechanger_name.as_hidden }}
{{ form.teamsnap_name.as_hidden }}
{{ form.id.as_hidden }}
{{ form.teamsnap_member_id.as_hidden }}
{{ form.fname.as_hidden }}
{{ form.lname.as_hidden }}
</tr>
{% endfor %}
</table>

View File

@@ -1,16 +1,10 @@
from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
from django.urls import path
from .views import (
PreferencesFormView,
AccountFormView,
roster_view,
roster_save
)
from .views import AccountFormView, PreferencesFormView, lineup_submit, roster_import
urlpatterns = [
path("account/", AccountFormView.as_view(), name="gamechanger_account"),
path("preferences/", PreferencesFormView.as_view(), name="gamechanger_preferences"),
path("roster/", roster_view, name="gamechanger_roster"),
path("roster/save", roster_save, name="gamechanger_save"),
path("roster/import", roster_import, name="gamechanger_import_roster"),
path("lineup/submit", lineup_submit, name="gamechanger_lineup_submit"),
]

View File

@@ -1,15 +1,70 @@
import requests
import re
import json
import re
import requests
url = "https://gc.com/t/{season_id}/{team_id}/{page}"
def get_authenticated_session(request):
gc_username = request.user.gamechanger_account.user
gc_password = request.user.gamechanger_account.password
s = requests.Session()
s.headers.update({"referer": "https://gc.com/do-login"})
s.get("https://gc.com/login")
r2 = s.post(
"https://gc.com/do-login",
cookies=s.cookies,
data={
"csrfmiddlewaretoken": s.cookies.get("csrftoken"),
"email": gc_username,
"password": gc_password,
},
)
if r2.status_code == 200:
return s
else:
raise requests.exceptions.RequestException(
f"Returned {r2.status_code} for {r2.reason}"
)
def submit_lineup(request, lineup):
authenticated_session = get_authenticated_session(request)
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
authenticated_session.headers.update(
{
"referer": url.format(
season_id=season_id, team_id=team_id, page="lineup_edit"
),
"x-csrftoken": authenticated_session.cookies.get("csrftoken"),
"Content-Type": "application/x-www-form-urlencoded;",
}
)
r = authenticated_session.post(
cookies=authenticated_session.cookies,
url="https://gc.com/do-save-lineup/{team_id}".format(
team_id=team_id.split("-").pop()
),
json={"lineup": lineup},
)
if r.status_code == 200:
return r
else:
raise requests.exceptions.RequestException(
f"Returned {r.status_code} for {r.reason}"
)
def scrape_page(season_id, team_id, page):
r = requests.get(url.format(season_id=season_id, team_id=team_id, page=page))
j=initialize_page_json = re.search(r'page.initialize\(\$.parseJSON\("(.*?)"\)', r.content.decode('unicode_escape'))
m=j.group(1)
initialize_page_json = re.search(
r'page.initialize\(\$.parseJSON\("(.*?)"\)', r.content.decode("unicode_escape")
)
m = initialize_page_json.group(1)
return json.loads(m)
# d = scrape_page(season_id, team_id, page)
pass

View File

@@ -1,11 +1,14 @@
from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError
from django.shortcuts import render
from django.views.generic.edit import FormView
from django.views.generic.list import ListView
from .forms import PreferencesForm, AccountForm, PlayerFormSet
from .utils.gamechanger import scrape_page
from teamsnap.views import get_teamsnap_client
# Create your views here.
from .forms import AccountForm, PlayerFormSet, PreferencesForm
from .models import Player
from .utils import gamechanger
class PreferencesFormView(FormView):
template_name = "gamechanger/form.html"
form_class = PreferencesForm
@@ -29,6 +32,7 @@ class PreferencesFormView(FormView):
return initial
class AccountFormView(FormView):
template_name = "gamechanger/form.html"
form_class = AccountForm
@@ -52,12 +56,15 @@ class AccountFormView(FormView):
return initial
def roster_view(request):
def roster_import(request):
if request.method == "GET":
from pyteamsnap.api import Member
client = get_teamsnap_client(request)
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
teamsnap_team_id = request.user.preferences.managed_team_id
teamsnap_team_id = request.user.teamsnap_preferences.managed_team_id
teamsnap_members = {
f"{member.data['first_name']} {member.data['last_name']}": member
for member in Member.search(client, team_id=teamsnap_team_id)
@@ -65,17 +72,103 @@ def roster_view(request):
page = "roster"
d = scrape_page(season_id, team_id, page)
roster = d['roster']
initial = [{
'gamechanger_name':f"{player['fname']} {player['lname']}",
'teamsnap_name':"{first_name} {last_name}".format(**teamsnap_members[f"{player['fname']} {player['lname']}"].data),
'gamechanger_id':player.get('player_id'),
'teamsnap_member_id':teamsnap_members[f"{player['fname']} {player['lname']}"].data['id'],
} for player in roster]
d = gamechanger.scrape_page(season_id, team_id, page)
roster = d["roster"]
initial = [
{
"gamechanger_name": f"{player['fname']} {player['lname']}",
"fname": player["fname"],
"lname": player["lname"],
"teamsnap_name": "{first_name} {last_name}".format(
**teamsnap_members[f"{player['fname']} {player['lname']}"].data
),
"id": player.get("player_id"),
"teamsnap_member_id": teamsnap_members[
f"{player['fname']} {player['lname']}"
].data["id"],
}
for player in roster
]
formset = PlayerFormSet(initial=initial)
return render(request, "gamechanger/roster.html", context={'roster':roster, 'formset':formset})
choices = [
(
teamsnap_member.data["id"],
f"{teamsnap_member.data['first_name']} {teamsnap_member.data['last_name']}",
)
for teamsnap_member in teamsnap_members.values()
]
for form in formset:
form.fields["teamsnap_member_id"].widget.choices = choices
pass
return render(
request,
"gamechanger/roster.html",
context={"roster": roster, "formset": formset},
)
elif request.POST:
formset = PlayerFormSet(request.POST)
if formset.is_valid():
r = []
for form in formset:
data = form.cleaned_data
data.pop("DELETE")
data.pop("gamechanger_name")
data.pop("teamsnap_name")
obj, did_create = Player.objects.update_or_create(**data)
obj.save()
r.append(obj)
return HttpResponse(status=200)
else:
return HttpResponseServerError()
def roster_save(request):
pass
return HttpResponseServerError()
else:
return HttpResponseServerError()
def lineup_submit(request):
from teamsnap.forms import LineupEntryFormset
if request.GET:
return HttpResponseNotAllowed()
if request.POST:
formset = LineupEntryFormset(request.POST)
if formset.is_valid():
lineup_data = [
form.cleaned_data
for form in formset
if form.cleaned_data.get("label")
and form.cleaned_data.get("sequence") is not None
]
lineup_data.sort(key=lambda x: x.get("sequence"))
lineup = []
for lineup_entry in lineup_data:
d = {
"player_id": lineup_entry["gamechanger_player_id"],
"position": lineup_entry["label"],
}
if lineup_entry["label"] == "DH":
for_whom = [
e
for e in lineup_data
if e["position_only"] and e["label"] != "DR"
][0]
d["forwhom"] = for_whom["gamechanger_player_id"]
lineup.append(d)
if for_whom in lineup:
lineup_data.remove(for_whom)
if for_whom in lineup_data:
lineup_data.remove(for_whom)
lineup.append(
{
"player_id": for_whom["gamechanger_player_id"],
"position": for_whom["label"],
}
)
elif lineup_entry["label"] != "DR":
lineup.append(d)
gamechanger.submit_lineup(request, lineup)
return HttpResponse(status=200)
return HttpResponseServerError()

View File

@@ -21,6 +21,7 @@ class LineupEntryForm(forms.Form):
member = None
availability = None
lineup_entry = None
gamechanger_player_id = forms.Field(required=False)
event_lineup_entry_id = forms.Field(required=False)
event_lineup_id = forms.Field(required=False)

View File

@@ -31,6 +31,7 @@ class Migration(migrations.Migration):
"user",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name='teamsnap_preferences',
to=settings.AUTH_USER_MODEL,
),
),

View File

View File

@@ -5,5 +5,10 @@ from benchcoach.users.models import User
class Preferences(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user = models.OneToOneField(
User, on_delete=models.CASCADE, related_name="teamsnap_preferences"
)
managed_team_id = models.IntegerField()
class Meta:
verbose_name_plural = "preferences"

View File

@@ -25,7 +25,6 @@
<tbody>
<tr class="align-top mx-1">
{% for event_data in contexts %}
<td class="px-1">
{% include "lineup/widgets/lineup.html" with event=event_data.event event_id=event_data.event.data.id formset=event_data.formset formset_startinglineup=event_data.formset_startinglineup formset_bench=event_data.formset_bench formset_out=event_data.formset_out formset_startingpositionalonly=event_data.formset_startingpositionalonly %}
</td>
@@ -41,25 +40,24 @@
{% block inline_javascript %}
{{ block.super }}
<script src="{% static 'js/Sortable.js' %}"></script>
<script src="{% static 'js/lineup-table.js' %}"></script>
<script>
window.addEventListener('DOMContentLoaded', () => {
/* Run whatever you want */
const postForms = document.querySelectorAll("[id^=form-lineup]");
for (postForm of postForms) {
function handleSubmit(postForm) {
postForm.addEventListener("submit", e => {
const postSubmits = document.querySelectorAll("[id^=submit-lineup]");
for (postSubmit of postSubmits) {
function handleSubmit(postSubmit) {
postSubmit.addEventListener("click", e => {
e.preventDefault();
formData = new FormData(postForm);
fetch(postForm.action, {
formData = new FormData(postSubmit.form);
fetch(postSubmit.formAction, {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(response => response)
.then(data => {
{#postForm.reset();#}
document.querySelector("#popup-messages-content").innerHTML = `<div class="alert alert-dismissible alert-success" role="alert">
<strong>Success!</strong> ${data.formatted_title} <strong>saved</strong>.
<strong>Success!</strong>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> `
})
@@ -69,7 +67,7 @@
})
}
handleSubmit(postForm)
handleSubmit(postSubmit)
}
});
</script>

View File

@@ -1,6 +1,6 @@
{% load static %}
<div class="card mx-auto benchcoach-lineup" style="max-width: 455px" id="benchcoach-lineup-{{ event_id }}">
<form method="post" action='{% url 'teamsnap_submit_lineup' team_id=event.data.team_id event_id=event.data.id %}' id="form-lineup-{{ event.data.id }}">
<form method="post" id="form-lineup-{{ event.data.id }}">
{{ formset.management_form }}
{% csrf_token %}
<div class="border-bottom p-2">
@@ -34,11 +34,17 @@
</ul>
</div>
<div>
<button class="btn btn-teamsnap btn-sm py-0 m-1" type="submit">
<button type="Submit" class="btn btn-teamsnap btn-sm py-0 m-1" formaction="{% url 'teamsnap_submit_lineup' team_id=event.data.team_id event_id=event.data.id %}" form="form-lineup-{{ event.data.id }}" id="submit-lineup-gamechanger-{{ event.data.id }}">
<i class="bi bi-arrow-right"></i>
TeamSnap
</button>
</div>
<div>
<button type="Submit" class="btn btn-gamechanger btn-sm py-0 m-1 text-nowrap" formaction="{% url 'gamechanger_lineup_submit' %}" form="form-lineup-{{ event.data.id }}" id="submit-lineup-gamechanger-{{ event.data.id }}">
<i class="bi bi-arrow-right"></i>
GameChanger
</button>
</div>
</div>
</div>
</div>

View File

@@ -8,6 +8,7 @@
data-player-name="{{ form.member.data.last_name }}, {{ form.member.data.first_name }}"
data-availability-statuscode="{{ form.availability.data.status_code }}"
>
{{ form.gamechanger_player_id.as_hidden }}
{{ form.event_lineup_entry_id.as_hidden }}
{{ form.event_lineup_id.as_hidden }}
{{ form.event_id.as_hidden }}

View File

@@ -7,10 +7,12 @@ from allauth.socialaccount.providers.oauth2.views import (
OAuth2CallbackView,
OAuth2LoginView,
)
from django.http import HttpResponseNotAllowed, HttpResponseServerError, JsonResponse
from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError
from django.shortcuts import redirect, render
from django.views.generic.edit import FormView
from gamechanger.models import Player as GamechangerPlayer
from .forms import PreferencesForm
from .models import Preferences
from .provider import TeamsnapProvider
@@ -120,7 +122,8 @@ class PreferencesFormView(FormView):
def schedule_view(request, team_id=None):
if not team_id:
return redirect(
"teamsnap_schedule", team_id=request.user.preferences.managed_team_id
"teamsnap_schedule",
team_id=request.user.teamsnap_preferences.managed_team_id,
)
client = get_teamsnap_client(request)
no_past = bool(request.GET.get("no_past", 0))
@@ -149,7 +152,7 @@ def schedule_view(request, team_id=None):
def view_event(request, event_id, team_id=None):
if not team_id:
return redirect(
"teamsnap_event", team_id=request.user.preferences.managed_team_id
"teamsnap_event", team_id=request.user.teamsnap_preferences.managed_team_id
)
from pyteamsnap.api import (
@@ -225,6 +228,16 @@ def edit_lineup(request, event_ids, team_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}
@@ -300,6 +313,9 @@ def edit_lineup(request, event_ids, team_id):
"member_id": member["member"]["id"],
"sequence": member["lineup_entry"].get("sequence"),
"label": position,
"gamechanger_player_id": gc_player_lookup.get(
member["member"]["id"]
),
}
)
@@ -360,7 +376,8 @@ def edit_lineup(request, event_ids, team_id):
def dashboard(request, team_id=None):
if not team_id:
return redirect(
"teamsnap_dashboard", team_id=request.user.preferences.managed_team_id
"teamsnap_dashboard",
team_id=request.user.teamsnap_preferences.managed_team_id,
)
from pyteamsnap.api import AvailabilitySummary, Event
@@ -395,12 +412,11 @@ def dashboard(request, team_id=None):
def submit_lineup(request, team_id, event_id):
from pyteamsnap.api import Event, EventLineup, EventLineupEntry
from pyteamsnap.api import EventLineup, EventLineupEntry
from teamsnap.forms import LineupEntryFormset
client = get_teamsnap_client(request)
ts_event = Event.get(client, event_id)
ts_lineup = EventLineup.search(client, event_id=event_id)
event_lineup_id = ts_lineup[0].data["id"]
if request.GET:
@@ -443,10 +459,6 @@ def submit_lineup(request, team_id, event_id):
else:
pass
else:
# breakpoint()
pass
# breakpoint()
pass
return JsonResponse(ts_event.data)
pass
return HttpResponseServerError
return HttpResponse(status=200)
return HttpResponseServerError()