adding gamechanger, in progress
This commit is contained in:
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="mb-1">
|
<div class="mb-1 bg-light">
|
||||||
<nav class="navbar navbar-expand-md navbar-dark bg-navbar">
|
<nav class="navbar navbar-expand-md navbar-dark bg-navbar">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler navbar-toggler-right" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
@@ -72,10 +72,18 @@
|
|||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="navbarDropdown">
|
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="navbarDropdown">
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item">
|
||||||
<a class="nav-link" href="{% url 'teamsnap_preferences' %}">{% translate "Preferences" %}</a>
|
<a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% translate "My Profile" %}</a>
|
||||||
|
</li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a class="nav-link" href="{% url 'teamsnap_preferences' %}">{% translate "TeamSnap Preferences" %}</a>
|
||||||
|
</li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li class="dropdown-item">
|
||||||
|
<a class="nav-link" href="{% url 'gamechanger_account' %}">{% translate "GameChanger Account" %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item">
|
||||||
<a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% translate "My Profile" %}</a>
|
<a class="nav-link" href="{% url 'gamechanger_preferences' %}">{% translate "GameChanger Preferences" %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li><hr class="dropdown-divider"></li>
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li class="dropdown-item">
|
<li class="dropdown-item">
|
||||||
@@ -107,7 +115,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container bg-light">
|
<div class="container">
|
||||||
|
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ SOCIALACCOUNT_FORMS = {"signup": "benchcoach.users.forms.UserSocialSignupForm"}
|
|||||||
|
|
||||||
# Your stuff...
|
# Your stuff...
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
INSTALLED_APPS += ["teamsnap", "instagen"]
|
INSTALLED_APPS += ["teamsnap", "instagen","gamechanger"]
|
||||||
SOCIALACCOUNT_PROVIDERS = {
|
SOCIALACCOUNT_PROVIDERS = {
|
||||||
'teamsnap': {
|
'teamsnap': {
|
||||||
'SCOPE': ["read", "write"]
|
'SCOPE': ["read", "write"]
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ urlpatterns = [
|
|||||||
path("accounts/", include("allauth.urls")),
|
path("accounts/", include("allauth.urls")),
|
||||||
path("", include("teamsnap.urls")),
|
path("", include("teamsnap.urls")),
|
||||||
path("", include("instagen.urls")),
|
path("", include("instagen.urls")),
|
||||||
|
path("gc/", include("gamechanger.urls"))
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
gamechanger/__init__.py
Normal file
0
gamechanger/__init__.py
Normal file
6
gamechanger/admin.py
Normal file
6
gamechanger/admin.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from .models import Account, Preferences
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
|
admin.site.register(Account)
|
||||||
|
admin.site.register(Preferences)
|
||||||
6
gamechanger/apps.py
Normal file
6
gamechanger/apps.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class GamechangerConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'gamechanger'
|
||||||
35
gamechanger/forms.py
Normal file
35
gamechanger/forms.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
from django import forms
|
||||||
|
from django.forms import ModelForm, formset_factory
|
||||||
|
|
||||||
|
from .models import Preferences, Account, Player
|
||||||
|
|
||||||
|
class PreferencesForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Preferences
|
||||||
|
fields = ["user", "season_id", "team_id"]
|
||||||
|
widgets = {
|
||||||
|
"user": forms.HiddenInput(),
|
||||||
|
"managed_team_id": forms.TextInput(),
|
||||||
|
}
|
||||||
|
labels = {"managed_team_id": "Selected Team"}
|
||||||
|
|
||||||
|
class AccountForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Account
|
||||||
|
fields = ["user", "email", "password"]
|
||||||
|
widgets = {
|
||||||
|
"user": forms.HiddenInput(),
|
||||||
|
"email": forms.EmailInput(),
|
||||||
|
"password": forms.PasswordInput()
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlayerForm(ModelForm):
|
||||||
|
gamechanger_name = forms.Field()
|
||||||
|
teamsnap_name = forms.Field()
|
||||||
|
gamechanger_id = forms.Field()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Player
|
||||||
|
fields = ['id', 'teamsnap_member_id']
|
||||||
|
|
||||||
|
PlayerFormSet = formset_factory(PlayerForm, can_delete=True, extra=0)
|
||||||
34
gamechanger/migrations/0001_initial.py
Normal file
34
gamechanger/migrations/0001_initial.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Generated by Django 3.2.13 on 2022-06-07 16:50
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Preferences',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('managed_team_id', models.IntegerField()),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='gamechanger_preferences', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Account',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('email', models.EmailField(max_length=254)),
|
||||||
|
('password', models.CharField(max_length=255)),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='gamechanger_account', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
29
gamechanger/migrations/0002_auto_20220607_1259.py
Normal file
29
gamechanger/migrations/0002_auto_20220607_1259.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 3.2.13 on 2022-06-07 17:59
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('gamechanger', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='preferences',
|
||||||
|
name='managed_team_id',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='preferences',
|
||||||
|
name='season_id',
|
||||||
|
field=models.CharField(default=1, max_length=255),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='preferences',
|
||||||
|
name='team_id',
|
||||||
|
field=models.CharField(default=1, max_length=255),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
0
gamechanger/migrations/__init__.py
Normal file
0
gamechanger/migrations/__init__.py
Normal file
20
gamechanger/models.py
Normal file
20
gamechanger/models.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
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")
|
||||||
|
email = EmailField()
|
||||||
|
password = CharField(max_length=255)
|
||||||
|
|
||||||
|
class Preferences(models.Model):
|
||||||
|
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 Player(models.Model):
|
||||||
|
id = models.AutoField(primary_key=True)
|
||||||
|
teamsnap_member_id = models.IntegerField()
|
||||||
|
fname = CharField(max_length=30)
|
||||||
|
lname = CharField(max_length=30)
|
||||||
7
gamechanger/templates/gamechanger/form.html
Normal file
7
gamechanger/templates/gamechanger/form.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<form method="post">{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input type="submit" value="Save">
|
||||||
|
</form>
|
||||||
|
{% endblock content %}
|
||||||
44
gamechanger/templates/gamechanger/roster.html
Normal file
44
gamechanger/templates/gamechanger/roster.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
{# {% for player in roster %}#}
|
||||||
|
{# <li class="list-group-item">#}
|
||||||
|
{# {{ player.fname }} {{ player.lname }}#}
|
||||||
|
{# </li>#}
|
||||||
|
{# {% endfor %}#}
|
||||||
|
<form method="post" action='{% url 'gamechanger_save' %}' >
|
||||||
|
{{ formset.management_form }}
|
||||||
|
{% csrf_token %}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ formset.0.gamechanger_name.label }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ formset.0.teamsnap_name.label }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ formset.0.DELETE.label }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% for form in formset %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ form.gamechanger_name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ form.teamsnap_name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ form.DELETE }}
|
||||||
|
</td>
|
||||||
|
{{ form.gamechanger_id.as_hidden }}
|
||||||
|
{{ form.teamsnap_member_id.as_hidden }}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<button class="btn btn-success" type="submit">
|
||||||
|
{# <i class="bi bi-arrow-right"></i>#}
|
||||||
|
Import
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
3
gamechanger/tests.py
Normal file
3
gamechanger/tests.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
16
gamechanger/urls.py
Normal file
16
gamechanger/urls.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from .views import (
|
||||||
|
PreferencesFormView,
|
||||||
|
AccountFormView,
|
||||||
|
roster_view,
|
||||||
|
roster_save
|
||||||
|
)
|
||||||
|
|
||||||
|
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"),
|
||||||
|
]
|
||||||
0
gamechanger/utils/__init__.py
Normal file
0
gamechanger/utils/__init__.py
Normal file
15
gamechanger/utils/gamechanger.py
Normal file
15
gamechanger/utils/gamechanger.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import requests
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
url = "https://gc.com/t/{season_id}/{team_id}/{page}"
|
||||||
|
|
||||||
|
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)
|
||||||
|
return json.loads(m)
|
||||||
|
# d = scrape_page(season_id, team_id, page)
|
||||||
|
pass
|
||||||
81
gamechanger/views.py
Normal file
81
gamechanger/views.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
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.
|
||||||
|
class PreferencesFormView(FormView):
|
||||||
|
template_name = "gamechanger/form.html"
|
||||||
|
form_class = PreferencesForm
|
||||||
|
success_url = "/"
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
# This method is called when valid form data has been POSTed.
|
||||||
|
# It should return an HttpResponse.
|
||||||
|
if form.data["user"] == str(self.request.user.id):
|
||||||
|
form.save()
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
"""
|
||||||
|
Returns the initial data to use for forms on this view.
|
||||||
|
"""
|
||||||
|
initial = super().get_initial()
|
||||||
|
initial["user"] = self.request.user
|
||||||
|
initial["email"] = self.request.user.username
|
||||||
|
# initial['managed_team_id']
|
||||||
|
|
||||||
|
return initial
|
||||||
|
|
||||||
|
class AccountFormView(FormView):
|
||||||
|
template_name = "gamechanger/form.html"
|
||||||
|
form_class = AccountForm
|
||||||
|
success_url = "/"
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
# This method is called when valid form data has been POSTed.
|
||||||
|
# It should return an HttpResponse.
|
||||||
|
if form.data["user"] == str(self.request.user.id):
|
||||||
|
form.save()
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
"""
|
||||||
|
Returns the initial data to use for forms on this view.
|
||||||
|
"""
|
||||||
|
initial = super().get_initial()
|
||||||
|
initial["user"] = self.request.user
|
||||||
|
initial["email"] = self.request.user.username
|
||||||
|
# initial['managed_team_id']
|
||||||
|
|
||||||
|
return initial
|
||||||
|
|
||||||
|
def roster_view(request):
|
||||||
|
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_members = {
|
||||||
|
f"{member.data['first_name']} {member.data['last_name']}":member
|
||||||
|
for member in Member.search(client, team_id=teamsnap_team_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
formset = PlayerFormSet(initial=initial)
|
||||||
|
return render(request, "gamechanger/roster.html", context={'roster':roster, 'formset':formset})
|
||||||
|
pass
|
||||||
|
|
||||||
|
def roster_save(request):
|
||||||
|
pass
|
||||||
@@ -12,33 +12,37 @@
|
|||||||
<button class="btn btn-primary btn-sm py-0 m-1" onclick="importFromClipboard(this)" type="button"><i class="bi bi-arrow-90deg-down"></i></i><i class="bi bi-file-spreadsheet"></i> </button>
|
<button class="btn btn-primary btn-sm py-0 m-1" onclick="importFromClipboard(this)" type="button"><i class="bi bi-arrow-90deg-down"></i></i><i class="bi bi-file-spreadsheet"></i> </button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-end d-inline">
|
<div class="col text-end d-inline">
|
||||||
<div class="dropdown">
|
<div class="btn-group">
|
||||||
<button class="btn btn-secondary dropdown-toggle btn-sm py-0 m-1" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
|
<div class="dropdown">
|
||||||
<i class="bi bi-share"></i> Export
|
<button class="btn btn-secondary dropdown-toggle btn-sm py-0 m-1" type="button" id="dropdownMenuButton1"
|
||||||
</button>
|
data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
|
<i class="bi bi-share"></i> Export
|
||||||
<li>
|
</button>
|
||||||
<a class="dropdown-item" href="javascript:;" onclick="copyEmailTable(this, '{{ event.data.start_date|date:"D, F j, Y g:i A" }}, {{ event.data.location_name }}, ({% if event.data.game_type == 'Away' %}@{% endif %}{{ event.data.opponent_name }})', '{% for form in formset %}{{ form.member.data.email_addresses.0 }},{% endfor %}')">
|
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
|
||||||
<i class="bi bi-envelope"></i> Generate Lineup Email
|
<li>
|
||||||
</a>
|
<a class="dropdown-item" href="javascript:;"
|
||||||
</li>
|
onclick="copyEmailTable(this, '{{ event.data.start_date|date:"D, F j, Y g:i A" }}, {{ event.data.location_name }}, ({% if event.data.game_type == 'Away' %}@{% endif %}{{ event.data.opponent_name }})', '
|
||||||
<li>
|
{% for form in formset %}{{ form.member.data.email_addresses.0 }},{% endfor %}')">
|
||||||
<a class="dropdown-item" onclick="sendToClipboard(this)">
|
<i class="bi bi-envelope"></i> Generate Lineup Email
|
||||||
<i class="bi bi-file-spreadsheet"></i> Sheet format to Clipboard
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
<li>
|
||||||
</ul>
|
<a class="dropdown-item" onclick="sendToClipboard(this)">
|
||||||
</div>
|
<i class="bi bi-file-spreadsheet"></i> Sheet format to Clipboard
|
||||||
<div>
|
</a>
|
||||||
<button class="btn btn-teamsnap btn-sm py-0 m-1" type="submit">
|
</li>
|
||||||
<i class="bi bi-arrow-right"></i>
|
</ul>
|
||||||
TeamSnap
|
</div>
|
||||||
</button>
|
<div>
|
||||||
|
<button class="btn btn-teamsnap btn-sm py-0 m-1" type="submit">
|
||||||
|
<i class="bi bi-arrow-right"></i>
|
||||||
|
TeamSnap
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body p-0 m-0">
|
<div class="card-body p-0 m-0">
|
||||||
<div>
|
<div>
|
||||||
<div class="row m-0">
|
<div class="row m-0">
|
||||||
|
|||||||
Reference in New Issue
Block a user