sync improvements

allow blank for teamsnap fields
This commit is contained in:
2021-12-22 15:21:36 -06:00
parent e0b9ed6d87
commit 3f39a7aa68
13 changed files with 189 additions and 590 deletions

View File

@@ -1 +0,0 @@
[{"model": "teamsnap.user", "pk": 1, "fields": {"teamsnap_id": "25560745", "access_token": "u2SqDq78FumVvhkt1D-V1CQ2ZIaB-nUVlzGwd1YhGtA"}}, {"model": "teamsnap.team", "pk": 1, "fields": {"teamsnap_id": "7644001", "name": null, "bencoach_team": null}}]

View File

@@ -1,25 +1,29 @@
from django import forms
from .models import LineupEntry, Event
import benchcoach.models
from .models import Team, Location, Opponent, Event, Member
from django.forms import modelformset_factory
class LineupEntryForm(forms.ModelForm):
availability = None
class Meta:
model = LineupEntry
widgets = {
'label': forms.Select(attrs={'class': 'form-control form-control-sm'})
}
exclude = ()
select_kwargs = {
'attrs':{'class': 'form-control form-control-sm'}
}
LineupEntryFormSet = modelformset_factory(
model=LineupEntry,
form=LineupEntryForm,
extra=0
)
text_input_kwargs = {
'attrs':{"readonly": "readonly", 'class':'form-control form-control-sm'}
}
class MemberForm(forms.ModelForm):
class Meta:
model = Member
fields = ('first_name', 'last_name', 'benchcoach_object')
labels = {
'benchcoach_object': 'BenchCoach Link',
}
widgets = {
"benchcoach_object": forms.Select(**select_kwargs),
"first_name": forms.TextInput(**text_input_kwargs),
"last_name": forms.TextInput(**text_input_kwargs),
}
class EventForm(forms.ModelForm):
availability = None
class Meta:
model = Event
fields = ('formatted_title', 'start_date', 'benchcoach_object')
@@ -29,12 +33,45 @@ class EventForm(forms.ModelForm):
'start_date':'Date/Time'
}
widgets = {
"formatted_title":forms.TextInput(attrs={"disabled":"disabled"}),
"start_date": forms.DateTimeInput(attrs={"disabled": "disabled"})
"benchcoach_object": forms.Select(**select_kwargs),
"formatted_title":forms.TextInput(**text_input_kwargs),
"start_date": forms.DateTimeInput(**text_input_kwargs)
}
EventFormSet = modelformset_factory(
model=Event,
form=EventForm,
extra=0
)
class TeamForm(forms.ModelForm):
class Meta:
model = Team
fields = ('name', 'benchcoach_object')
labels ={
'benchcoach_object':'BenchCoach Link',
}
widgets = {
"name":forms.TextInput(**text_input_kwargs),
"benchcoach_object": forms.Select(**select_kwargs)
}
class OpponentForm(forms.ModelForm):
class Meta:
model = Opponent
fields = ('name', 'benchcoach_object')
labels ={
'benchcoach_object':'BenchCoach Link',
}
widgets = {
"name":forms.TextInput(**text_input_kwargs),
"benchcoach_object": forms.Select(**select_kwargs)
}
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = ('name', 'benchcoach_object')
labels ={
'benchcoach_object':'BenchCoach Link',
}
widgets = {
"name":forms.TextInput(**text_input_kwargs),
"benchcoach_object": forms.Select(**select_kwargs)
}

View File

@@ -0,0 +1,23 @@
# Generated by Django 3.2.6 on 2021-12-22 15:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('teamsnap', '0003_auto_20211219_2058'),
]
operations = [
migrations.AlterField(
model_name='event',
name='is_game',
field=models.BooleanField(null=True),
),
migrations.AlterField(
model_name='member',
name='is_non_player',
field=models.BooleanField(null=True),
),
]

View File

@@ -26,6 +26,7 @@ class Team(TeamsnapBaseModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Team,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_team"
)
@@ -35,7 +36,8 @@ class Team(TeamsnapBaseModel):
def update_or_create_from_teamsnap_api(cls, teamsnap_data):
fields = ['id', 'name', 'created_at', 'updated_at']
data = {k: teamsnap_data[k] for k in fields}
team, created = cls.objects.update_or_create(**data)
id = data.pop('id')
team, created = cls.objects.update_or_create(id=id, defaults=data)
return (team, created)
class User(TeamsnapBaseModel):
@@ -55,7 +57,8 @@ class User(TeamsnapBaseModel):
obj, created = Team.objects.get_or_create(id=managed_team_id)
managed_teams.append(obj)
pass
user, created = cls.objects.update_or_create(**user_data)
id = user_data.pop('id')
user, created = cls.objects.update_or_create(id=id, defaults=user_data)
user.managed_teams.add(*managed_teams)
return (user, created)
@@ -80,6 +83,7 @@ class Opponent(TeamsnapManagedObjectModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Team,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_opponent"
)
@@ -90,8 +94,10 @@ class Opponent(TeamsnapManagedObjectModel):
fields = ['id', 'name', 'created_at', 'updated_at']
opponent_data = {k: teamsnap_data[k] for k in fields}
team, created = Team.objects.get_or_create(id=teamsnap_data['team_id'])
opponent, created = cls.objects.update_or_create(**opponent_data)
id = opponent_data.pop('id')
opponent, created = cls.objects.update_or_create(id=id, defaults=opponent_data)
opponent.team = team
opponent.save()
return (opponent, created)
class Location(TeamsnapManagedObjectModel):
@@ -100,6 +106,7 @@ class Location(TeamsnapManagedObjectModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Venue,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_location"
)
@@ -110,8 +117,10 @@ class Location(TeamsnapManagedObjectModel):
fields = ['id', 'name', 'created_at', 'updated_at']
opponent_data = {k: teamsnap_data[k] for k in fields}
team, created = Team.objects.get_or_create(id=teamsnap_data['team_id'])
location, created = cls.objects.update_or_create(**opponent_data)
id = opponent_data.pop('id')
location, created = cls.objects.update_or_create(id=id, defaults=opponent_data)
location.team = team
location.save()
return (location, created)
class Member(TeamsnapManagedObjectModel):
@@ -123,13 +132,14 @@ class Member(TeamsnapManagedObjectModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Player,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_member"
)
first_name = models.CharField(max_length = 50, null=True)
last_name = models.CharField(max_length = 50, null=True)
jersey_number = models.IntegerField(null=True)
is_non_player = models.BooleanField()
is_non_player = models.BooleanField(null=True)
ApiObject = teamsnap.teamsnap.api.Member
@classmethod
@@ -137,8 +147,10 @@ class Member(TeamsnapManagedObjectModel):
fields = ['id', 'created_at', 'updated_at', 'first_name', 'last_name', 'jersey_number','is_non_player']
member_data = {k: teamsnap_data[k] for k in fields}
team, created = Team.objects.get_or_create(id=teamsnap_data['team_id'])
member, created = cls.objects.update_or_create(**member_data)
id = member_data.pop('id')
member, created = cls.objects.update_or_create(id=id, defaults= member_data)
member.team = team
member.save()
return (member, created)
def __str__(self):
@@ -156,6 +168,7 @@ class Event(TeamsnapManagedObjectModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Event,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_event"
)
@@ -166,7 +179,7 @@ class Event(TeamsnapManagedObjectModel):
formatted_title = models.CharField(max_length = 50, null=True)
points_for_opponent = models.PositiveSmallIntegerField(null=True)
points_for_team = models.PositiveSmallIntegerField(null=True)
is_game = models.BooleanField()
is_game = models.BooleanField(null=True)
game_type = models.CharField(max_length = 50, null=True)
ApiObject = teamsnap.teamsnap.api.Event
@@ -187,13 +200,15 @@ class Event(TeamsnapManagedObjectModel):
event_data = {k: teamsnap_data[k] for k in fields}
location, created = Location.objects.get_or_create(id=teamsnap_data['location_id'])
team, created = Team.objects.get_or_create(id=teamsnap_data['team_id'])
event, created = cls.objects.update_or_create(**event_data)
id = event_data.pop('id')
event, created = cls.objects.update_or_create(id=id, defaults=event_data)
event.location = location
if teamsnap_data['opponent_id']:
opponent, created = Opponent.objects.get_or_create(id=teamsnap_data['opponent_id'])
event.opponent = opponent
event.team = team
return (location, created)
event.save()
return (team, created)
def __str__(self):
return f"{self.formatted_title} ({self.id})"
@@ -214,6 +229,7 @@ class Availability(TeamsnapManagedObjectModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Availability,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_availability"
)
@@ -238,10 +254,12 @@ class Availability(TeamsnapManagedObjectModel):
member, created = Member.objects.get_or_create(id=teamsnap_data['member_id'])
team, created = Team.objects.get_or_create(id=teamsnap_data['team_id'])
event, created = Event.objects.get_or_create(id=teamsnap_data['event_id'])
availability, created = cls.objects.update_or_create(**availability_data)
id = availability_data.pop('id')
availability, created = cls.objects.update_or_create(id=id, defaults=availability_data)
availability.team = team
availability.event = event
availability.member = member
availability.save()
return (availability, created)
class LineupEntry(TeamsnapManagedObjectModel):
@@ -263,6 +281,7 @@ class LineupEntry(TeamsnapManagedObjectModel):
benchcoach_object = models.OneToOneField(
benchcoach.models.Positioning,
null=True,
blank=True,
on_delete=models.CASCADE,
related_name="teamsnap_lineupentry"
)
@@ -283,8 +302,10 @@ class LineupEntry(TeamsnapManagedObjectModel):
member, created = Member.objects.get_or_create(id=teamsnap_data['member_id'])
team, created = Team.objects.get_or_create(id=teamsnap_data['team_id'])
event, created = Event.objects.get_or_create(id=teamsnap_data['event_id'])
lineup_entry, created = cls.objects.update_or_create(**lineup_entry_data)
id = lineup_entry_data.pop('id')
lineup_entry, created = cls.objects.update_or_create(id=id, defaults=lineup_entry_data)
lineup_entry.team = team
lineup_entry.event = event
lineup_entry.member = member
lineup_entry.save()
return (lineup_entry, created)

View File

@@ -1,23 +0,0 @@
{% extends "base.html" %}
{% block title %} {{ title }}{% endblock %}
{% block content %}
<h1>{{ title }}</h1>
{#<ol class="list-group">#}
{% for item in object_list %}
<ul class="card">
<span class="card-title">{{ item.formatted_title }}</span>
<span class="fs-6">{{ item.subtitle }}</span>
{# {% if item.body %}#}
{# <br><span class="fs-6">{{ item.body }}</span>#}
<br>{{ item.start_date|date:"D, M j, g:i A" }},<br>{{item.location.name}}
{# {% endif %}#}
<br>
{% for button in item.buttons %}
<a class="btn btn-primary btn-sm" href="{{ button.href }}" role="button">{{ button.label }}</a>
{% endfor %}
</ul>
{% endfor %}
</ol>
{% endblock %}

View File

@@ -7,32 +7,30 @@
<p><b>TeamSnap: </b>{{ teamsnap_user.email }}</p>
<p><b>TeamSnap Managed Team: </b>{{ teamsnap_team.name }}</p>
<button type="button" class="btn btn-primary m-1" onclick="sync_teamsnap_db()">
Sync TeamSnap DB
<button type="button" class="btn btn-primary m-1" onclick="sync_teamsnapdb_with_teamsnapapi()">
Sync TeamSnapDB with TeamSnap.com
<div id="teamsnap-sync-spinner" class="spinner-border spinner-border-sm d-none" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</button>
<button type="button" class="btn btn-primary m-1" onclick="sync_teamsnap_db()">
Sync TeamSnap DB
<div id="teamsnap-sync-spinner" class="spinner-border spinner-border-sm d-none" role="status">
<button type="button" class="btn btn-primary m-1" onclick="sync_teamsnapdb_to_benchcoachdb()">
Sync BenchCoachDB with TeamSnapDB
<div id="benchcoach-sync-spinner" class="spinner-border spinner-border-sm d-none" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</button>
{% include 'messages.html' %}
<div id="message-area"> </div>
<script>
const progress_spinner = document.getElementById("teamsnap-sync-spinner")
const message_area = document.getElementById("message-area")
function sync_teamsnap_db(){
function sync_teamsnapdb_with_teamsnapapi(){
const progress_spinner = document.getElementById("teamsnap-sync-spinner")
const Http = new XMLHttpRequest();
const url='{% url 'sync teamsnap db' %}';
console.log(progress_spinner)
const url='{% url 'sync with teamsnapapi' %}';
progress_spinner.classList.remove("d-none");
fetch(url)
.then((response) => {
progress_spinner.classList.add("d-none")
message_area.innerText = "test"
return response.json();
})
.then((myJson) => {
@@ -41,15 +39,16 @@
});
}
function sync_teamsnap_db_2(){
function sync_teamsnapdb_to_benchcoachdb(){
console.log('hello')
const progress_spinner = document.getElementById("benchcoach-sync-spinner")
const Http = new XMLHttpRequest();
const url='{% url 'sync teamsnap db' %}';
console.log(progress_spinner)
const url='{% url 'sync benchcoach' %}';
console.log(url)
progress_spinner.classList.remove("d-none");
fetch(url)
.then((response) => {
progress_spinner.classList.add("d-none")
message_area.innerText = "test"
return response.json();
})
.then((myJson) => {

View File

@@ -1,157 +0,0 @@
{% extends 'base.html' %}{% block title %} {{ title }} {% endblock %}{% load static %}
{% block content %}
<div class="w-100 text-center mx-auto text-center">
<h1 class="display-5 fw-bold"><a href="#" class="btn btn-primary btn-secondary p-1 mx-3"><</a>{{ event.formatted_title }}<a href="#" class="btn btn-primary btn-secondary p-1 mx-3">></a></h1>
<div class="lead">
<p class="">{{ event.start_date|date:"l, F j, Y g:i A" }}<br>{{ event.location.name }}</p>
</div>
</div>
<div class="container">
<form action="{% url 'teamsnap edit lineup' event_id=event.id%}" method="post">
{% csrf_token %}
{{ formset.management_form }}
<div class="row">
{# <input type="submit" value="Submit" class="btn btn-sm btn-success mx-3 my-0 my-0">#}
<div class="col-md-6">
<div class="card my-1">
<div class="card-header"><h5>Lineup</h5></div>
<div class="card-body p-0">
{% include 'teamsnap/player-table.html' with table_id="lineup" formset=formset_lineup available_class="d-none"%}
<div class="justify-content-md-end d-md-flex m-2"><input type="submit" value="Submit" class="btn btn-primary"></div>
</div>
</div>
<div class="card my-1">
<div class="card-header"><h5>DH'd</h5></div>
<div class="card-body p-0">
{% include 'teamsnap/player-table.html' with table_id="dhd" formset=formset_dhd available_class="d-none" sequence_class="d-none"%}
<div class="justify-content-md-end d-md-flex m-2"><input type="submit" value="Submit" class="btn btn-primary"></div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card my-1">
<div class="card-header"><h5>Bench</h5></div>
<div class="card-body p-0">
{% include 'teamsnap/player-table.html' with table_id="bench" formset=formset_bench sequence_class="d-none"%}
</div>
</div>
</div>
</div>
</form>
</div>
<script src="{% static 'js/Sortable.js' %}"></script>
<script id="sortable">
function refresh_lineup_sequence (){
var member_rows = document.getElementById('lineup').querySelectorAll('tr')
var has_dh = false
for (let i = 0; i < member_rows.length; i++) {
if (member_rows[i].dataset.sequence == 0) {
has_dh = true
continue
}
if (has_dh) {
member_rows[i].dataset.sequence = i
}
else {
member_rows[i].dataset.sequence = i+1
}
var member_sequence = member_rows[i].querySelector('[id^="member-sequence-button"]')
var form_element_sequence = member_rows[i].querySelector('[id$="sequence"]')
member_sequence.innerText = parseInt(member_rows[i].dataset.sequence)
form_element_sequence.value = parseInt(member_rows[i].dataset.sequence)
}
}
var lineup = new Sortable.create(
document.getElementById('dhd'), {
animation: 150,
ghostClass: "ghost",
{#handle: ".bars-move",#}
group: {
put: true,
pull: true
}
})
var lineup = new Sortable.create(
document.getElementById('lineup'), {
animation: 150,
ghostClass:"ghost",
{#handle: ".bars-move",#}
group:{
put:true,
pull:true
},
onAdd: function (/**Event*/evt) {
// Add to Lineup
var itemEl = evt.item; // dragged HTMLElement
var member_id = itemEl.dataset.memberId
console.log(itemEl)
var form_element_sequence =itemEl.querySelector('[id$="sequence"]')
var member_sequence = itemEl.querySelector('[id^="member-sequence"]')
var member_available =itemEl.querySelector('[id^="member-available"]')
var member_sequence_button =itemEl.querySelector('[id^="member-sequence-button"]')
console.log(member_sequence.parentElement.dataset)
toggle_in_lineup(member_sequence_button)
member_sequence.parentElement.dataset.sequence = evt.newIndex
refresh_lineup_sequence()
{#member_available.parentElement.style.display="none"#}
member_available.parentElement.classList.add('d-none')
{#member_sequence.style.display="table-cell"#}
member_sequence.classList.remove('d-none')
},
onUpdate: function (/**Event*/evt) {
console.log('update to lineup')
var itemEl = evt.item; // dragged HTMLElement
refresh_lineup_sequence()
},
});
var bench = new Sortable.create(
document.getElementById('bench'), {
animation: 150,
ghostClass:"ghost",
sort: false,
{#handle: ".bars-move",#}
group:{
put:true,
pull:true
},
onAdd: function (/**Event*/evt) {
console.log('added to bench')
var itemEl = evt.item; // dragged HTMLElement
console.log(itemEl)
var form_element_sequence =itemEl.querySelector('[id$="sequence"]')
var member_sequence = itemEl.querySelector('[id^="member-sequence"]')
var member_available =itemEl.querySelector('[id^="member-available"]')
{#member_available.parentElement.style.display="table-cell"#}
member_available.parentElement.classList.remove('d-none')
form_element_sequence.value = 0
member_sequence.innerHTML = 1
{#member_sequence.style.display="none"#}
member_sequence.classList.add('d-none')
var member_id = itemEl.dataset.memberId
refresh_lineup_sequence()
}
});
function toggle_in_lineup(sequence_button){
var member_row = sequence_button.parentNode.parentNode
if (member_row.dataset.sequence == 0) {
sequence_button.innerText = "1"
sequence_button.classList.add("btn-light")
sequence_button.classList.remove("btn-dark")
member_row.dataset.sequence = 1
}
else {
sequence_button.innerText = "D"
sequence_button.classList.remove("btn-light")
sequence_button.classList.add("btn-dark")
member_row.dataset.sequence = 0
}
refresh_lineup_sequence()
}
</script>
{% endblock %}

View File

@@ -1,86 +0,0 @@
<table class="table">
<thead>
<tr class="border border-light">
{# <th scope="col" style="display: none"></th>#}
{# <th scope="col" class="border border-light"></th>#}
{# <th scope="col">Name</th>#}
{# <th scope="col">Pos</th>#}
</tr>
</thead>
<tbody id={{ table_id }}>
{% for form in formset %}
<tr data-member-id="{{ form.instance.member.id }}"
data-position="{{ form.instance.position }}"
data-sequence="{{ form.instance.sequence }}">
{{ form.id.as_hidden }}
{{ form.event.as_hidden }}
{{ form.sequence.as_hidden }}
{{ form.member.as_hidden }}
{{ form.teamsnap_id.as_hidden }}
<td id="member-availability-{{ form.instance.member.id }}"
class="{{ available_class }}"
>
{% if form.availability.status_code == 2 %}
<button class="btn btn-light bg-info p-1"
id="member-available-{{ form.instance.member.id }}"
>
<span style="visibility: hidden">2</span>
<span class="visually-hidden">Maybe</span>
</button>
{% elif form.availability.status_code == 1%}
<button class="btn btn-light bg-success p-1"
id="member-available-{{ form.instance.member.id }}"
>
<span style="visibility: hidden">1</span>
</button>
<span class="visually-hidden">Maybe</span>
{% elif form.availability.status_code == 0%}
<button class="btn btn-light bg-danger p-1"
id="member-available-{{ form.instance.member.id }}"
>
<span style="visibility: hidden">0</span>
</button>
<span class="visually-hidden">No</span>
{% else %}
<button class="btn btn-light bg-secondary p-1"
id="member-available-{{ form.instance.member.id }}"
>
<span style="visibility: hidden">X</span>
</button>
<span class="visually-hidden">Unknown</span>
{% endif %}
</td>
<th scope="row"
id="member-sequence-{{ form.instance.member.id }}"
class="{{ sequence_class }}">
{% if form.sequence.value %}
<button type="button"
class="btn btn-light p-1"
id="member-sequence-button-{{ form.instance.member.id }}"
onclick="toggle_in_lineup(this)"
>
{{ form.sequence.value }}
</button>
{% elif form.sequence.value == 0 %}
<button type="button"
class="btn btn-dark p-1"s
id="member-sequence-button-{{ form.instance.member.id }}"
onclick="toggle_in_lineup(this)"
>
D
</button>
{% endif %}
</th>
<th>
{{ form.instance.member.first_name }}&nbsp;{{ form.instance.member.last_name }}&nbsp;
<small class="text-muted fw-light">#{{ form.instance.member.jersey_number }}</small>
{# <br><code><small>{{ form.statline }}</small></code>#}
</th>
<td>
{{ form.label }}
</td>
{# <td>{{ form.instance.position }}</td>#}
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -1,13 +1,8 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ formset.management_form }}
<table>
{% extends 'base.html' %}
{% block content %}
<form method="post">
{{ formset.management_form }}{% csrf_token %}
<table class="table">
<tr>
{% for _, field in formset.0.base_fields.items %}
<th>{{ field.label }}</th>
@@ -24,6 +19,6 @@
</tr>
{% endfor %}
</table>
</body>
</html>
<input type="submit" value="Submit">
</form>
{% endblock %}

View File

@@ -7,9 +7,11 @@ from . import views
urlpatterns = [
path('', views.home, name='teamsnap home'),
path('events', views.EventsListView.as_view(), name="teamsnap list events"),
path('events-table', views.EventsTableView.as_view(), name="teamsnap table events"),
# path('events', views.EventsListView.as_view(), name="teamsnap list events"),
# path('event-table', views.EventsTableView.as_view(), name="teamsnap table events"),
path('table/<str:object>', views.TeamsnapObjTableView.as_view(), name="teamsnap table obj"),
path('edit/event/<int:id>', views.edit_event, name='teamsnap edit event'),
path('sync_teamsnap_db', views.sync_teamsnap_db, name="sync teamsnap db"),
path('sync_teamsnap_db', views.sync_teamsnapdb_with_teamsnapapi, name="sync with teamsnapapi"),
path('sync_benchcoach_db', views.sync_teamsnapdb_to_benchcoachdb, name="sync benchcoach"),
# path('import_teamsnap', views.import_teamsnap, name="import teamsnap"),
]

View File

@@ -29,9 +29,10 @@ def update_teamsnap_object(d, teamsnap_object: TeamsnapBaseModel, benchcoach_mod
if teamsnap_object.benchcoach_object:
#TODO I'm not sure this does anything. need to make sure.
benchcoach_object = benchcoach_model.objects.filter(id=teamsnap_object.benchcoach_object.id).first()
benchcoach_object = benchcoach_model.objects.filter(id=teamsnap_object.benchcoach_object.id)
benchcoach_object.update(**d)
created = False
r.append((benchcoach_object, created))
r.append((benchcoach_object.first(), created))
elif not teamsnap_object.benchcoach_object and create_benchcoach_object:
benchcoach_object = benchcoach_model(**d) # create new benchcoach object
teamsnap_object.benchcoach_object = benchcoach_object

View File

@@ -1,198 +0,0 @@
import os
import sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "benchcoachproject.settings")
os.environ["DJANGO_SETTINGS_MODULE"] = "benchcoachproject.settings"
import django
django.setup()
from teamsnap.teamsnap.api import TeamSnap
import teamsnap.teamsnap.api
from teamsnap.models import User, Member, Team, Event, Location, Availability, Opponent, TeamsnapBaseModel
from typing import List, Type, Tuple
from benchcoachproject.models import Profile as BenchcoachUser
import benchcoach.models
from django.db import models
import pytz
def update_teamsnapbasemodel_from_teamsnap(
TeamsnapModel: Type[TeamsnapBaseModel],
teamsnap_client: teamsnap.teamsnap.api.TeamSnap,
fields: List[str]= ['created_at', 'updated_at'],
additional_fields: List[str] = [],
related_fields: List[Tuple[str, Type[TeamsnapBaseModel]]] = [],
create = True,
create_related = True,
**teamsnap_search_kwargs
):
api_response_objects = TeamsnapModel.ApiObject.search(
client=teamsnap_client, **teamsnap_search_kwargs
)
r = []
for response_object in api_response_objects:
d = {k:response_object.data[k] for k in fields}
d.update({k:response_object.data[k] for k in additional_fields})
for related_field_name, RelatedTeamSnapModel in related_fields:
related_field_name = f"{related_field_name}_id"
filter_criteria = {related_field_name:response_object.data[related_field_name]}
if related_field_name == "team_id" and RelatedTeamSnapModel.__name__ == "Team":
filter_criteria = {'id':response_object.data[related_field_name]}
related_teamsnap_object = RelatedTeamSnapModel.objects.filter(**filter_criteria).first()
if related_teamsnap_object:
d[related_field_name] = related_teamsnap_object
elif not related_teamsnap_object and create_related:
related_teamsnap_object = RelatedTeamSnapModel(**{related_field_name:response_object.data[related_field_name]})
related_teamsnap_object.save()
elif not related_teamsnap_object and not create_related:
raise RelatedTeamSnapModel.DoesNotExist
teamsnap_object = TeamsnapModel.objects.filter(id=response_object.data['id'])
if teamsnap_object:
teamsnap_object.update(**d)
created = False
r.append((teamsnap_object.first(), created))
elif not teamsnap_object and create:
new_teamsnap_object = TeamsnapModel(**d) # create new benchcoach object
new_teamsnap_object.save()
created = True
r.append((new_teamsnap_object, created))
elif not teamsnap_object and not create:
raise TeamsnapModel.DoesNotExist
return r
def update_events(
teamsnap_client: teamsnap.teamsnap.api.TeamSnap,
create: bool = True,
create_related: bool = False,
**teamsnap_search_kwargs
):
r = update_teamsnapbasemodel_from_teamsnap(
TeamsnapModel= Event,
teamsnap_client= teamsnap_client,
additional_fields=['label', 'start_date', 'formatted_title', 'points_for_opponent', 'points_for_team', 'is_game', 'game_type'],
related_fields=[('location', Location), ('opponent', Opponent), ('team', Team)],
create=create,
create_related=create_related,
**teamsnap_search_kwargs
)
return r
def update_opponents(
teamsnap_client: teamsnap.teamsnap.api.TeamSnap,
create: bool = True,
create_related: bool = False,
**teamsnap_search_kwargs
):
r = update_teamsnapbasemodel_from_teamsnap(
TeamsnapModel= Opponent,
teamsnap_client= teamsnap_client,
additional_fields=['name'],
related_fields=[('team', Team)],
create=create,
create_related=create_related,
**teamsnap_search_kwargs
)
return r
def update_teams(
teamsnap_client: teamsnap.teamsnap.api.TeamSnap,
create: bool = True,
create_related: bool = False,
**teamsnap_search_kwargs
):
r = update_teamsnapbasemodel_from_teamsnap(
TeamsnapModel=Team,
teamsnap_client=teamsnap_client,
additional_fields=['name'],
create=create,
create_related=create_related,
**teamsnap_search_kwargs
)
def update_locations(
teamsnap_client: teamsnap.teamsnap.api.TeamSnap,
create: bool = True,
create_related: bool = False,
**teamsnap_search_kwargs
):
r = update_teamsnapbasemodel_from_teamsnap(
TeamsnapModel=Location,
teamsnap_client=teamsnap_client,
additional_fields=['name'],
related_fields=[('team', Team)],
create=create,
create_related=create_related,
**teamsnap_search_kwargs
)
def update_availabilities(teamsnap_client: teamsnap.teamsnap.api.TeamSnap,
create: bool = True,
create_related: bool = False,
**teamsnap_search_kwargs
):
r = update_teamsnapbasemodel_from_teamsnap(
TeamsnapModel= Availability,
teamsnap_client= teamsnap_client,
related_fields=[('event', Event), ('member', Member), ('team', Team)],
create=create,
create_related=create_related,
**teamsnap_search_kwargs
)
def import_teamsnap():
user = BenchcoachUser.objects.get(id=1)
TOKEN = user.teamsnap_access_token
USER_ID = user.teamsnap_user.id
TEAM_ID = user.teamsnapsettings.managed_team.id
CLIENT = TeamSnap(token=TOKEN)
l = []
for team in Opponent.objects.filter(managed_by_team_id=TEAM_ID):
l += update_opponent(team, create_benchcoach_object=True, create_related=True)
for team in Team.objects.filter(id=TEAM_ID):
l += update_team(team, create_benchcoach_object=True, create_related=True)
for location in Location.objects.filter(managed_by_team_id=TEAM_ID):
l += update_location(location, create_benchcoach_object=True, create_related=True)
for member in Member.objects.filter(managed_by_team_id=TEAM_ID, is_non_player=False):
l += update_member(member, create_benchcoach_object= True, create_related=True)
for event in Event.objects.filter(managed_by_team_id=TEAM_ID):
l += update_event(event, create_benchcoach_object=True, create_related=True)
for availability in Availability.objects.filter(managed_by_team_id=TEAM_ID):
l += update_availability(availability, create_benchcoach_object=True, create_related=True)
pass
# l += update_teams(CLIENT, team_id=TEAM_ID)
# l += update_members(CLIENT, team_id=TEAM_ID)
# l += update_locations(CLIENT, team_id=TEAM_ID)
# l += update_events(CLIENT, team_id=TEAM_ID)
# l += update_availabilities(CLIENT, team_id=TEAM_ID)
if __name__ == "__main__":
TOKEN = BenchcoachUser.objects.get(id=1).teamsnap_access_token
USER_ID = BenchcoachUser.objects.get(id=1).teamsnap_user_id
TEAM_ID = BenchcoachUser.objects.get(id=1).teamsnapsettings.managed_team_id
CLIENT = TeamSnap(token=TOKEN)
for Obj in [User]:
a = Obj.ApiObject.search(CLIENT, id=USER_ID)
for _a in a:
obj, created = Obj.update_or_create_from_teamsnap_api(_a.data)
for Obj in [Event, Availability, Location, Member, Opponent, Team]:
a = Obj.ApiObject.search(CLIENT, team_id=TEAM_ID)
for _a in a:
obj, created = Obj.update_or_create_from_teamsnap_api(_a.data)
# update_opponents(CLIENT, team_id=TEAM_ID)
# update_events(CLIENT, team_id=TEAM_ID)

View File

@@ -4,20 +4,20 @@ from .teamsnap.api import Event as TsApiEvent
from .teamsnap.api import TeamSnap
from .models import User, Member, Team, Event, Location, LineupEntry, Opponent, Availability
from lib.views import BenchcoachListView
from .forms import LineupEntryForm, LineupEntryFormSet, EventForm, EventFormSet
from .forms import EventForm, MemberForm, OpponentForm, TeamForm, LocationForm
from django.urls import reverse
from django.db.models import Case, When
from django.views import View
from django.http import HttpResponse
import benchcoachproject.models
import benchcoach.models
import teamsnap.teamsnap.api
import json
from django.http import JsonResponse
from .utils.teamsnap_object_utils import update_users, update_teams, update_events, update_members, update_locations, update_availabilities
from django.contrib import messages
from django.template.loader import render_to_string
from .utils.import_teamsnap import update_team, update_event, update_member, update_location, update_opponent, update_availability, update_teamsnap_object
from django.forms import modelformset_factory
import django.db.models
def queryset_from_ids(Model, id_list):
#https://stackoverflow.com/questions/4916851/django-get-a-queryset-from-array-of-ids-in-specific-order
@@ -40,61 +40,45 @@ def home(request):
}
return render(request, 'teamsnap/home.html', context)
class EventsTableView(View):
def get(self, request):
qs = Event.objects.all()
formset = EventFormSet(queryset=qs)
return render(request,'teamsnap/event-table.html', context={'formset':formset})
class TeamsnapObjTableView(View):
Model = None
Form = None
template = 'teamsnap/table.html'
options = {
'event': (Event, EventForm),
'location': (Location, LocationForm),
'member': (Member, MemberForm),
'opponent': (Opponent, OpponentForm),
'team': (Team, TeamForm)
}
class EventsListView(BenchcoachListView):
Model = Event
edit_url = 'teamsnap edit event'
list_url = 'teamsnap list events'
page_title = "TeamSnap Events"
title_strf = '{item.formatted_title}'
body_strf = "{item.start_date:%a, %b %-d, %-I:%M %p},\n{item.location.name}"
def post(self, request, object):
self.Model, self.Form = self.options[object]
self.Formset = modelformset_factory(
model=self.Model,
form=self.Form,
extra=0
)
formset = self.Formset(request.POST, request.FILES)
if formset.is_valid():
formset.save()
return HttpResponse(200)
else:
return HttpResponse(422)
pass
def get_context_data(self):
context = super().get_context_data()
for item in context['items']:
item['buttons'].append(
{
'label': 'Edit Lineup',
'href': reverse('teamsnap edit lineup', args=[item['id']])
}
)
return context
def get(self, request, object):
self.Model, self.Form = self.options[object]
self.Formset = modelformset_factory(
model=self.Model,
form=self.Form,
extra=0
)
qs = self.Model.objects.all()
formset = self.Formset(queryset=qs)
return render(request, self.template, context={'formset': formset})
class TeamListView(BenchcoachListView):
Model = Team
edit_url = 'teamsnap edit team'
list_url = 'teamsnap list teams'
page_title = "TeamSnap Teams"
class LocationListView(BenchcoachListView):
Model = Location
edit_url = 'teamsnap edit location'
list_url = 'teamsnap list locations'
page_title = "TeamSnap Locations"
def update_from_teamsnap_event(request):
TOKEN = benchcoachproject.models.User.objects.get(id=1).teamsnap_access_token
CLIENT = TeamSnap(token=TOKEN)
teamsnap_event_id=request.POST.get('teamsnap event')
benchcoach_event_id=request.POST.get('teamsnap event')
if teamsnap_event_id:
benchcoach_event = benchcoach.models.Event.objects.get(id=benchcoach_event_id)
teamsnap_object = benchcoach.models.Event.objects.get(id=teamsnap_event_id)
teamsnap_id = teamsnap_object.teamsnap_id
teamsnap_response = TsApiEvent.search(client=CLIENT, id=teamsnap_id)
if teamsnap_response[0]:
data = teamsnap_response[0].data
location = Location.objects.get(teamsnap_id=data['location_id'])
opponent = Team.objects.get(teamsnap_id=data['opponent_id'])
return HttpResponse(f'Success, {data}')
def sync_with_teamsnap_api(request):
def sync_teamsnapdb_with_teamsnapapi(request):
'''
This sync the internal TeamSnap Database with the TeamSnap API
'''
@@ -119,6 +103,7 @@ def sync_with_teamsnap_api(request):
obj, created = Obj.update_or_create_from_teamsnap_api(_a.data)
r[Obj.__name__].append((obj, created))
for object_name, results in r.items():
if len(r) == 0:
messages.error(request, f"Error! No {object_name} objects created or updated")
@@ -132,7 +117,7 @@ def sync_with_teamsnap_api(request):
return JsonResponse(data)
def sync_teamsnap_db(request):
def sync_teamsnapdb_to_benchcoachdb(request):
'''
This syncs the internal BenchCoach Database and the TeamSnap Database
'''
@@ -148,7 +133,7 @@ def sync_teamsnap_db(request):
r['location'] = []
for location in Location.objects.filter(team_id=TEAM_ID):
r['team/location'] += update_location(location, create_benchcoach_object=True, create_related=True)
r['location'] += update_location(location, create_benchcoach_object=True, create_related=True)
r['member'] = []
for member in Member.objects.filter(team_id=TEAM_ID, is_non_player=False):
@@ -159,8 +144,9 @@ def sync_teamsnap_db(request):
r['event'] += update_event(event, create_benchcoach_object=True, create_related=True)
r['availability'] = []
for availability in Availability.objects.filter(team_id=TEAM_ID):
for availability in Availability.objects.filter(team_id=TEAM_ID, member__is_non_player=False):
r['availability'] += update_availability(availability, create_benchcoach_object=True, create_related=True)
pass
for object_name, results in r.items():
if len(r) == 0: