first init of this template.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from django import forms
|
||||
from .models import Team, Location, Opponent, Event, Member
|
||||
from django.forms import modelformset_factory
|
||||
from django.forms import modelformset_factory, formset_factory, inlineformset_factory
|
||||
|
||||
select_kwargs = {
|
||||
'attrs':{'class': 'form-control form-control-sm'}
|
||||
@@ -74,4 +74,45 @@ class LocationForm(forms.ModelForm):
|
||||
"benchcoach_object": forms.Select(**select_kwargs)
|
||||
}
|
||||
|
||||
class LineupEntryForm(forms.Form):
|
||||
member = None
|
||||
availability = None
|
||||
lineup_entry = None
|
||||
|
||||
event_lineup_entry_id = forms.Field(required=False)
|
||||
event_lineup_id = forms.Field(required=False)
|
||||
event_id = forms.Field()
|
||||
member_id = forms.Field()
|
||||
sequence = forms.IntegerField(required=False)
|
||||
label = forms.ChoiceField(required=False, choices=[
|
||||
("--", "--"),
|
||||
("P","P"),
|
||||
("C","C"),
|
||||
("1B","1B"),
|
||||
("2B", "2B"),
|
||||
("3B", "3B"),
|
||||
("SS", "SS"),
|
||||
('LF','LF'),
|
||||
('CF','CF'),
|
||||
('RF','RF'),
|
||||
('DH','DH'),
|
||||
('DR','DR'),
|
||||
('EH','EH')
|
||||
],
|
||||
widget=forms.Select(
|
||||
attrs = {'onchange' : "colorPositions();"}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class EventChooseForm(forms.Form):
|
||||
event_id = forms.ChoiceField()
|
||||
|
||||
# checked = forms.BooleanField(required=False)
|
||||
# def __init__(self, events, *args, **kwargs):
|
||||
# super(EventChooseForm, self).__init__(*args, **kwargs)
|
||||
# self.fields['foo'].choices = [e.data['id'] for e in events]
|
||||
|
||||
LineupEntryFormset = formset_factory(LineupEntryForm, can_delete=True, can_order=True, extra=0)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.db import models
|
||||
|
||||
import benchcoach.models
|
||||
import teamsnap.teamsnap.api
|
||||
import pyteamsnap.api
|
||||
from django.utils.timezone import localtime
|
||||
|
||||
class TeamsnapBaseModel(models.Model):
|
||||
@@ -9,7 +9,7 @@ class TeamsnapBaseModel(models.Model):
|
||||
id = models.CharField(max_length=50, unique=True, primary_key=True)
|
||||
created_at = models.DateTimeField(null=True)
|
||||
updated_at = models.DateTimeField(null=True)
|
||||
ApiObject = teamsnap.teamsnap.api.ApiObject
|
||||
ApiObject = pyteamsnap.api.ApiObject
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
@@ -29,7 +29,7 @@ class Team(TeamsnapBaseModel):
|
||||
on_delete=models.CASCADE,
|
||||
related_name="teamsnap_team"
|
||||
)
|
||||
ApiObject = teamsnap.teamsnap.api.Team
|
||||
ApiObject = pyteamsnap.api.Team
|
||||
|
||||
class User(TeamsnapBaseModel):
|
||||
type = 'user'
|
||||
@@ -37,7 +37,7 @@ class User(TeamsnapBaseModel):
|
||||
last_name = models.CharField(max_length = 50, null=True)
|
||||
email = models.EmailField(null=True)
|
||||
managed_teams = models.ManyToManyField(Team)
|
||||
ApiObject = teamsnap.teamsnap.api.User
|
||||
ApiObject = pyteamsnap.api.User
|
||||
|
||||
@classmethod
|
||||
def update_or_create_from_teamsnap_api(cls, teamsnap_data):
|
||||
@@ -76,7 +76,7 @@ class Opponent(TeamsnapManagedObjectModel):
|
||||
on_delete=models.CASCADE,
|
||||
related_name="teamsnap_opponent"
|
||||
)
|
||||
ApiObject = teamsnap.teamsnap.api.Opponent
|
||||
ApiObject = pyteamsnap.api.Opponent
|
||||
|
||||
class Location(TeamsnapManagedObjectModel):
|
||||
type = 'location'
|
||||
@@ -86,7 +86,7 @@ class Location(TeamsnapManagedObjectModel):
|
||||
on_delete=models.CASCADE,
|
||||
related_name="teamsnap_location"
|
||||
)
|
||||
ApiObject = teamsnap.teamsnap.api.Location
|
||||
ApiObject = pyteamsnap.api.Location
|
||||
|
||||
class Member(TeamsnapManagedObjectModel):
|
||||
# url format is
|
||||
@@ -103,7 +103,7 @@ class Member(TeamsnapManagedObjectModel):
|
||||
last_name = models.CharField(max_length = 50, null=True)
|
||||
jersey_number = models.IntegerField(null=True)
|
||||
is_non_player = models.BooleanField(null=True)
|
||||
ApiObject = teamsnap.teamsnap.api.Member
|
||||
ApiObject = pyteamsnap.api.Member
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.last_name}, {self.first_name} ({self.id})"
|
||||
@@ -131,7 +131,7 @@ class Event(TeamsnapManagedObjectModel):
|
||||
points_for_team = models.PositiveSmallIntegerField(null=True)
|
||||
is_game = models.BooleanField(null=True)
|
||||
game_type = models.CharField(max_length = 50, null=True)
|
||||
ApiObject = teamsnap.teamsnap.api.Event
|
||||
ApiObject = pyteamsnap.api.Event
|
||||
|
||||
@property
|
||||
def csv_event_title(self)->str:
|
||||
@@ -166,7 +166,7 @@ class Availability(TeamsnapManagedObjectModel):
|
||||
related_name="teamsnap_availability"
|
||||
)
|
||||
status_code = models.SmallIntegerField(choices=status_codes, null=True, blank=True, default=None)
|
||||
ApiObject = teamsnap.teamsnap.api.Availability
|
||||
ApiObject = pyteamsnap.api.Availability
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.member} - {self.event} ({self.id})"
|
||||
@@ -197,7 +197,7 @@ class LineupEntry(TeamsnapManagedObjectModel):
|
||||
)
|
||||
label = models.PositiveSmallIntegerField(choices=positions, default=None, null=True, blank=True)
|
||||
sequence = models.PositiveSmallIntegerField(default=0, null=True, blank=True)
|
||||
ApiObject = teamsnap.teamsnap.api.EventLineupEntry
|
||||
ApiObject = pyteamsnap.api.EventLineupEntry
|
||||
|
||||
@classmethod
|
||||
def update_or_create_from_teamsnap_api(cls, teamsnap_data):
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# from .utils import TeamSnap
|
||||
#
|
||||
# __all__ = ['TeamSnap']
|
||||
@@ -1,618 +0,0 @@
|
||||
__all__ = ['TeamSnap', 'Team', 'Event', 'Availability', 'Member', 'Location', 'Me']
|
||||
from apiclient import APIClient, HeaderAuthentication, JsonResponseHandler
|
||||
|
||||
class ApiObject():
|
||||
rel = None
|
||||
version = None
|
||||
template = None
|
||||
|
||||
def __init__(self, client, rel=rel, data={}):
|
||||
self.client = client
|
||||
self.data = data
|
||||
self.rel = rel
|
||||
|
||||
@classmethod
|
||||
def search(cls, client, **kwargs):
|
||||
results = client.query(cls.rel, "search", **kwargs)
|
||||
return [cls(client,rel=cls.rel, data=r) for r in results]
|
||||
|
||||
@classmethod
|
||||
def get(cls, client, id):
|
||||
r = client.get(f"{client.link(cls.rel)}/{id}")
|
||||
return cls(client, cls.rel, client.parse_response(r)[0])
|
||||
|
||||
class Me (ApiObject):
|
||||
rel = "me"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "first_name"
|
||||
},
|
||||
{
|
||||
"name": "last_name"
|
||||
},
|
||||
{
|
||||
"name": "password"
|
||||
},
|
||||
{
|
||||
"name": "birthday"
|
||||
},
|
||||
{
|
||||
"name": "email"
|
||||
},
|
||||
{
|
||||
"name": "facebook_id",
|
||||
"deprecated": True,
|
||||
"prompt": "facebook_id is deprecated and has been removed. Continued use of facebook_id is not recommended it will no longer be stored."
|
||||
},
|
||||
{
|
||||
"name": "facebook_access_token",
|
||||
"deprecated": True,
|
||||
"prompt": "facebook_access_token is deprecated and has been removed. Continued use of facebook_access_token is not recommended it will no longer be stored."
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "user"
|
||||
},
|
||||
{
|
||||
"name": "is_lab_rat"
|
||||
},
|
||||
{
|
||||
"name": "receives_newsletter"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
def __init__(self, client):
|
||||
super().__init__(client=client, rel=self.rel, data=client.get(client.link(self.rel)))
|
||||
|
||||
class User (ApiObject):
|
||||
rel = "users"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "first_name"
|
||||
},
|
||||
{
|
||||
"name": "last_name"
|
||||
},
|
||||
{
|
||||
"name": "password"
|
||||
},
|
||||
{
|
||||
"name": "birthday"
|
||||
},
|
||||
{
|
||||
"name": "email"
|
||||
},
|
||||
{
|
||||
"name": "facebook_id",
|
||||
"deprecated": True,
|
||||
"prompt": "facebook_id is deprecated and has been removed. Continued use of facebook_id is not recommended it will no longer be stored."
|
||||
},
|
||||
{
|
||||
"name": "facebook_access_token",
|
||||
"deprecated": True,
|
||||
"prompt": "facebook_access_token is deprecated and has been removed. Continued use of facebook_access_token is not recommended it will no longer be stored."
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "user"
|
||||
},
|
||||
{
|
||||
"name": "is_lab_rat"
|
||||
},
|
||||
{
|
||||
"name": "receives_newsletter"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class Event (ApiObject):
|
||||
rel = "events"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "type",
|
||||
"value": "event"
|
||||
},
|
||||
{
|
||||
"name": "additional_location_details"
|
||||
},
|
||||
{
|
||||
"name": "browser_time_zone"
|
||||
},
|
||||
{
|
||||
"name": "division_location_id"
|
||||
},
|
||||
{
|
||||
"name": "doesnt_count_towards_record"
|
||||
},
|
||||
{
|
||||
"name": "duration_in_minutes"
|
||||
},
|
||||
{
|
||||
"name": "game_type_code"
|
||||
},
|
||||
{
|
||||
"name": "icon_color"
|
||||
},
|
||||
{
|
||||
"name": "is_canceled"
|
||||
},
|
||||
{
|
||||
"name": "is_game"
|
||||
},
|
||||
{
|
||||
"name": "is_overtime"
|
||||
},
|
||||
{
|
||||
"name": "is_shootout"
|
||||
},
|
||||
{
|
||||
"name": "is_tbd"
|
||||
},
|
||||
{
|
||||
"name": "label"
|
||||
},
|
||||
{
|
||||
"name": "location_id"
|
||||
},
|
||||
{
|
||||
"name": "minutes_to_arrive_early"
|
||||
},
|
||||
{
|
||||
"name": "name"
|
||||
},
|
||||
{
|
||||
"name": "notes"
|
||||
},
|
||||
{
|
||||
"name": "notify_opponent"
|
||||
},
|
||||
{
|
||||
"name": "notify_opponent_contacts_email"
|
||||
},
|
||||
{
|
||||
"name": "notify_opponent_contacts_name"
|
||||
},
|
||||
{
|
||||
"name": "notify_opponent_notes"
|
||||
},
|
||||
{
|
||||
"name": "notify_team"
|
||||
},
|
||||
{
|
||||
"name": "notify_team_as_member_id"
|
||||
},
|
||||
{
|
||||
"name": "opponent_id"
|
||||
},
|
||||
{
|
||||
"name": "points_for_opponent"
|
||||
},
|
||||
{
|
||||
"name": "points_for_team"
|
||||
},
|
||||
{
|
||||
"name": "repeating_include",
|
||||
"prompt": "When updating a repeating event, this is a required field. Values are: \"all\" - updates all events in this series, \"future\" - updates this event and all that occur after, \"none\" - only updates a single event."
|
||||
},
|
||||
{
|
||||
"name": "repeating_type_code",
|
||||
"prompt": "A code for the frequency of the repeated event, this is required with the \"repeating_include\" attribute when creating a repeating event. Valid values are: \"1\" - repeat an event daily, \"2\" - repeat an event weekly."
|
||||
},
|
||||
{
|
||||
"name": "repeating_until",
|
||||
"prompt": "A date when the repeating event should end, this is inclusive so an event will be created on this day if it falls before the next event specified by \"repeating_type_code\". This attribute is required with \"repeating_type_code\" when creating a repeating event."
|
||||
},
|
||||
{
|
||||
"name": "results"
|
||||
},
|
||||
{
|
||||
"name": "results_url"
|
||||
},
|
||||
{
|
||||
"name": "shootout_points_for_opponent"
|
||||
},
|
||||
{
|
||||
"name": "shootout_points_for_team"
|
||||
},
|
||||
{
|
||||
"name": "start_date"
|
||||
},
|
||||
{
|
||||
"name": "team_id"
|
||||
},
|
||||
{
|
||||
"name": "time_zone"
|
||||
},
|
||||
{
|
||||
"name": "tracks_availability"
|
||||
},
|
||||
{
|
||||
"name": "uniform"
|
||||
}
|
||||
]}
|
||||
|
||||
class Team (ApiObject):
|
||||
rel = "teams"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "name"
|
||||
},
|
||||
{
|
||||
"name": "location_country"
|
||||
},
|
||||
{
|
||||
"name": "location_postal_code"
|
||||
},
|
||||
{
|
||||
"name": "time_zone",
|
||||
"prompt": "The time_zone parameter is required when creating a team, but for changing a team's time_zone, use the update_time_zone command"
|
||||
},
|
||||
{
|
||||
"name": "sport_id"
|
||||
},
|
||||
{
|
||||
"name": "division_id"
|
||||
},
|
||||
{
|
||||
"name": "division_name"
|
||||
},
|
||||
{
|
||||
"name": "season_name"
|
||||
},
|
||||
{
|
||||
"name": "league_name"
|
||||
},
|
||||
{
|
||||
"name": "league_url"
|
||||
},
|
||||
{
|
||||
"name": "owner_first_name"
|
||||
},
|
||||
{
|
||||
"name": "owner_last_name"
|
||||
},
|
||||
{
|
||||
"name": "owner_email"
|
||||
},
|
||||
{
|
||||
"name": "is_ownership_pending"
|
||||
},
|
||||
{
|
||||
"name": "ad_unit_hero_id"
|
||||
},
|
||||
{
|
||||
"name": "ad_unit_hero_template_id"
|
||||
},
|
||||
{
|
||||
"name": "ad_unit_inline_id"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "team"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class Availability (ApiObject):
|
||||
rel = "availabilities"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "status_code"
|
||||
},
|
||||
{
|
||||
"name": "notes"
|
||||
},
|
||||
{
|
||||
"name": "event_id"
|
||||
},
|
||||
{
|
||||
"name": "member_id"
|
||||
},
|
||||
{
|
||||
"name": "notes_author_member_id"
|
||||
},
|
||||
{
|
||||
"name": "source"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "availability"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class Member (ApiObject):
|
||||
rel = "members"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "first_name"
|
||||
},
|
||||
{
|
||||
"name": "last_name"
|
||||
},
|
||||
{
|
||||
"name": "gender"
|
||||
},
|
||||
{
|
||||
"name": "position"
|
||||
},
|
||||
{
|
||||
"name": "is_manager"
|
||||
},
|
||||
{
|
||||
"name": "birthday"
|
||||
},
|
||||
{
|
||||
"name": "hide_age",
|
||||
"deprecated": True,
|
||||
"prompt": "hide_age is deprecated and will be removed in a future version, use is_age_hidden instead."
|
||||
},
|
||||
{
|
||||
"name": "is_age_hidden"
|
||||
},
|
||||
{
|
||||
"name": "hide_address",
|
||||
"deprecated": True,
|
||||
"prompt": "hide_address is deprecated and will be removed in a future version, use is_address_hidden instead."
|
||||
},
|
||||
{
|
||||
"name": "is_address_hidden"
|
||||
},
|
||||
{
|
||||
"name": "is_non_player"
|
||||
},
|
||||
{
|
||||
"name": "address_street1"
|
||||
},
|
||||
{
|
||||
"name": "address_street2"
|
||||
},
|
||||
{
|
||||
"name": "address_city"
|
||||
},
|
||||
{
|
||||
"name": "address_state"
|
||||
},
|
||||
{
|
||||
"name": "address_zip"
|
||||
},
|
||||
{
|
||||
"name": "jersey_number"
|
||||
},
|
||||
{
|
||||
"name": "team_id"
|
||||
},
|
||||
{
|
||||
"name": "is_ownership_pending"
|
||||
},
|
||||
{
|
||||
"name": "source_action"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "member"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
class Location (ApiObject):
|
||||
rel = "locations"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "name"
|
||||
},
|
||||
{
|
||||
"name": "url"
|
||||
},
|
||||
{
|
||||
"name": "phone"
|
||||
},
|
||||
{
|
||||
"name": "notes"
|
||||
},
|
||||
{
|
||||
"name": "address"
|
||||
},
|
||||
{
|
||||
"name": "latitude"
|
||||
},
|
||||
{
|
||||
"name": "longitude"
|
||||
},
|
||||
{
|
||||
"name": "team_id"
|
||||
},
|
||||
{
|
||||
"name": "is_retired"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "location"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class Opponent (ApiObject):
|
||||
rel = "opponents"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "name"
|
||||
},
|
||||
{
|
||||
"name": "contacts_name"
|
||||
},
|
||||
{
|
||||
"name": "contacts_phone"
|
||||
},
|
||||
{
|
||||
"name": "contacts_email"
|
||||
},
|
||||
{
|
||||
"name": "notes"
|
||||
},
|
||||
{
|
||||
"name": "team_id"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "opponent"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class EventLineupEntry (ApiObject):
|
||||
rel = "event_lineup_entries"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "event_lineup_id"
|
||||
},
|
||||
{
|
||||
"name": "member_id"
|
||||
},
|
||||
{
|
||||
"name": "sequence"
|
||||
},
|
||||
{
|
||||
"name": "label"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "event_lineup_entry"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class Statistics (ApiObject):
|
||||
rel = "statistics"
|
||||
version = "3.866.0"
|
||||
template = {
|
||||
"data": [
|
||||
{
|
||||
"name": "acronym"
|
||||
},
|
||||
{
|
||||
"name": "always_display_decimals"
|
||||
},
|
||||
{
|
||||
"name": "formula"
|
||||
},
|
||||
{
|
||||
"name": "is_in_descending_order"
|
||||
},
|
||||
{
|
||||
"name": "display_zero_totals"
|
||||
},
|
||||
{
|
||||
"name": "is_percentage"
|
||||
},
|
||||
{
|
||||
"name": "is_private"
|
||||
},
|
||||
{
|
||||
"name": "is_team_statistic"
|
||||
},
|
||||
{
|
||||
"name": "is_top_statistic"
|
||||
},
|
||||
{
|
||||
"name": "name"
|
||||
},
|
||||
{
|
||||
"name": "precision"
|
||||
},
|
||||
{
|
||||
"name": "statistic_group_id"
|
||||
},
|
||||
{
|
||||
"name": "team_id"
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"value": "statistic"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
class MemberStatistics (ApiObject):
|
||||
rel = "member_statistics"
|
||||
|
||||
class TeamSnap(APIClient):
|
||||
base_url = 'https://api.teamsnap.com/v3'
|
||||
|
||||
def __init__(self, token, *args, **kwargs):
|
||||
super().__init__(*args,
|
||||
authentication_method=HeaderAuthentication(token=token),
|
||||
response_handler=JsonResponseHandler,
|
||||
**kwargs)
|
||||
self._root_collection = self.get(self.base_url)['collection']
|
||||
self._links = self._by_rel(self.base_url, 'links')
|
||||
self._queries = self._by_rel(self.base_url, 'queries')
|
||||
self._commands = self._by_rel(self.base_url, 'commands')
|
||||
pass
|
||||
|
||||
def link(self, link_name):
|
||||
d = {l['rel']:l['href'] for l in self._root_collection["links"]}
|
||||
return d.get(link_name)
|
||||
|
||||
def _by_rel (self, url, k):
|
||||
try:
|
||||
{l['rel']: l for l in self._root_collection[k]}
|
||||
except Exception as e:
|
||||
return {}
|
||||
self.get(url)['collection'][k]
|
||||
return {l['rel']:l for l in self.get(url)['collection'][k]}
|
||||
|
||||
def query (self, rel, query, **kwargs):
|
||||
queries = self._by_rel(self._get_href(rel), 'queries')
|
||||
response = self.get(self._get_href(query, queries), params=kwargs)
|
||||
return self.parse_response(response)
|
||||
|
||||
def command (self, rel, command, **kwargs):
|
||||
commands = self._by_rel(self._get_href(rel), 'commands')
|
||||
response = self.get(self._get_href(command, commands), params=kwargs)
|
||||
return self.parse_response(response)
|
||||
|
||||
def _get_href (self, rel: str, links:dict = None, url = base_url) -> str:
|
||||
"""returns a hyperlink from a the links dictionary. Each item in the links dictionary is a
|
||||
dictionary with a rel and href key"""
|
||||
if links is None: links = self._by_rel(url, 'links')
|
||||
link = links[rel]['href']
|
||||
return link
|
||||
|
||||
def get_item (self, rel, id):
|
||||
r = self.get(f"{self.link(rel)}/{id}")
|
||||
return self.parse_response(r)[0]
|
||||
|
||||
@classmethod
|
||||
def parse_response(self, response):
|
||||
result = []
|
||||
items = [item['data'] for item in response['collection'].get('items',[])]
|
||||
for item in response['collection'].get('items',[]):
|
||||
details = {}
|
||||
for detail in item['data']:
|
||||
# TODO type casting and validation based on item['type']
|
||||
details[detail['name']] = detail['value']
|
||||
result.append(details)
|
||||
|
||||
return result
|
||||
# return [{detail['name']: detail['value'] for detail in item} for item in items]
|
||||
|
||||
27
teamsnap/templates/teamsnap/availabilities.html
Normal file
27
teamsnap/templates/teamsnap/availabilities.html
Normal file
@@ -0,0 +1,27 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ title }}{% endblock %}
|
||||
{% block page_heading %}Schedule{% endblock %}
|
||||
{% block content %}
|
||||
{% load tz %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for event in events %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'teamsnap_event' id=event.data.id team_id=schedule.html %}">{{ event.data.formatted_title }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ event.data.start_date | localtime}}
|
||||
</td>
|
||||
<td>
|
||||
{{ event.data.location_name }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,116 +0,0 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ event.data.formatted_title }}{% endblock %}
|
||||
{% block page_heading %}{{ event.data.formatted_title }}{% endblock %}
|
||||
{% block page_subheading %}{{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h6>Lineup</h6>
|
||||
<form method="post" action="{% url 'teamsnap_submit_lineup' team_id=team_id event_id=event_id %}">
|
||||
{{ formset.management_form }}
|
||||
{% csrf_token %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm" id="table-event-lineup">
|
||||
<tbody id="tablebody-event-lineup">
|
||||
{% for form in formset %}
|
||||
{% if form.event_lineup_entry_id.value %}
|
||||
<tr>
|
||||
{{ form.event_lineup_entry_id.as_hidden }}
|
||||
{{ form.event_lineup_id.as_hidden }}
|
||||
{{ form.event_id.as_hidden }}
|
||||
{{ form.member_id.as_hidden }}
|
||||
{{ form.sequence.as_hidden }}
|
||||
{{ form.label.as_hidden }}
|
||||
{{ form.member_name.as_hidden }}
|
||||
|
||||
<td class="col-1 px-1">
|
||||
{{ forloop.counter }}
|
||||
</td>
|
||||
<td class="col-auto">
|
||||
{{ form.member_name.value }}
|
||||
</td>
|
||||
<td class="col-3">
|
||||
<div class="form-select-sm">{{ form.label }}</div>
|
||||
</td>
|
||||
<td class="col-1">
|
||||
<div class="d-flex">
|
||||
<div class="px-1">
|
||||
<i class="bi bi-dash-circle text-danger"></i>
|
||||
{{ form.DELETE.as_hidden }}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="col-1 drag-handle">
|
||||
<i class="bi bi-grip-vertical text-secondary"></i>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<input class="btn btn-success" type="submit" value="Submit">
|
||||
</form>
|
||||
<h6>Bench</h6>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# <th scope="row">#}
|
||||
{# <td>Status</td>#}
|
||||
{# <td>Last</td>#}
|
||||
{# <td>First</td>#}
|
||||
{# </th>#}
|
||||
{# </thead>#}
|
||||
|
||||
{% for availability in availablities %}
|
||||
{% if availability.data.member_is_non_player is False %}
|
||||
<tr>
|
||||
<td class="col-1">
|
||||
{% if availability.data.status_code == 1 %}
|
||||
<i class="bi bi-check-circle-fill text-success"></i>
|
||||
{% endif %}
|
||||
{% if availability.data.status_code == 0 %}
|
||||
<i class="bi bi-x-circle-fill text-danger"></i>
|
||||
{% endif %}
|
||||
{% if availability.data.status_code == None %}
|
||||
<i class="bi bi-circle"></i>
|
||||
{% endif %}
|
||||
{% if availability.data.status_code == 2 %}
|
||||
<i class="bi bi-circle-half text-info"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col-auto">
|
||||
{{ availability.data.member_first_name }} {{ availability.data.member_last_name }}
|
||||
</td>
|
||||
<td class="col-3">
|
||||
</td>
|
||||
<td class="col-1">
|
||||
<div class="d-flex">
|
||||
<div class="px-1">
|
||||
<i class="bi bi-plus-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/Sortable.js' %}"></script>
|
||||
<script id="sortable">
|
||||
var lineup = new Sortable.create(
|
||||
document.getElementById('tablebody-event-lineup'), {
|
||||
animation: 150,
|
||||
ghostClass:"ghost",
|
||||
handle: ".drag-handle",
|
||||
group:{
|
||||
put:true,
|
||||
pull:true
|
||||
},
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
76
teamsnap/templates/teamsnap/event/instagen.html
Normal file
76
teamsnap/templates/teamsnap/event/instagen.html
Normal file
@@ -0,0 +1,76 @@
|
||||
<html lang="en">
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ event.data.formatted_title }} - Instagenerator{% endblock %}
|
||||
{% block page_heading %}
|
||||
<div class="row d-inline-flex">
|
||||
<div class="col">
|
||||
<img src="{% static 'teamsnap/ig/graphics/hounds-insta.jpg' %}" class="mx-auto d-block img-fluid shadow-sm" style="height:30px;border-radius: 8px;">
|
||||
</div>
|
||||
<div class="col text-nowrap px-0">Hounds Instagenerator</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block page_subheading %}{{ event.data.formatted_title }}, {{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<form method="get" action="generate">
|
||||
|
||||
<div class="mb-3">
|
||||
<select hidden class="form-select" name="game_id" id="game_id">
|
||||
<optgroup label="Events">
|
||||
<option value="" disabled="disabled">Select an event...</option>
|
||||
<option selected value="{{event.data.id}}">{{event.data.formatted_title}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<legend class="">Background</legend>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="background" id="backgroundLocation" checked value="location">
|
||||
<label class="form-check-label" for="backgroundLocation">
|
||||
Location
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="background" id="backgroundTransparent" value="transparent">
|
||||
<label class="form-check-label" for="backgroundTransparent">
|
||||
Transparent
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="background" id="badge_only" value="badge">
|
||||
<label class="form-check-label" for="badge_only">
|
||||
Badge only
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<legend class="">Layout</legend>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="dimensions" id="square" checked value="1080x1080">
|
||||
<label class="form-check-label" for="square">
|
||||
Square
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="dimensions" id="portrait" value="1080x1920">
|
||||
<label class="form-check-label" for="portrait">
|
||||
Portrait
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="dimensions" id="portrait" value="1920x1080">
|
||||
<label class="form-check-label" for="portrait">
|
||||
Landscape
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-lg-flex justify-content-lg-end align-items-lg-center mb-3">
|
||||
<button type="submit" class="btn btn-primary btn-block">Get Image</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
12
teamsnap/templates/teamsnap/lineup/edit.html
Normal file
12
teamsnap/templates/teamsnap/lineup/edit.html
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ event.data.formatted_title }}{% endblock %}
|
||||
{% block page_heading %}{{ event.data.formatted_title }}{% endblock %}
|
||||
{% block page_subheading %}{{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'teamsnap/lineup/widgets/lineup.html' with formset_lineup=formset_lineup formset_bench=formset_bench%}
|
||||
|
||||
<script src="{% static 'js/Sortable.js' %}"></script>
|
||||
<script src="{% static 'teamsnap/js/lineup-table.js' %}"></script>
|
||||
|
||||
{% endblock %}
|
||||
95
teamsnap/templates/teamsnap/lineup/multiple_choose.html
Normal file
95
teamsnap/templates/teamsnap/lineup/multiple_choose.html
Normal file
@@ -0,0 +1,95 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ title }}{% endblock %}
|
||||
|
||||
{% csrf_token %}
|
||||
|
||||
{% block page_heading %}
|
||||
<div class="row d-inline-flex">
|
||||
<div class="col">
|
||||
Schedule
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<form method="get" action="{% url 'teamsnap_edit_multiple_lineups' team_id=team_id%}">
|
||||
{{ formset.management_form }}
|
||||
<input class="btn btn-sm btn-outline-primary text-nowrap" type="submit" value="Submit">
|
||||
{% load tz %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for form in formset %}
|
||||
<tr>
|
||||
{{ form.event_id }}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- create_normal.html :: part 4 -->
|
||||
|
||||
<script type='text/javascript'>
|
||||
function updateElementIndex(el, prefix, ndx) {
|
||||
var id_regex = new RegExp('(' + prefix + '-\\d+)');
|
||||
var replacement = prefix + '-' + ndx;
|
||||
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
|
||||
if (el.id) el.id = el.id.replace(id_regex, replacement);
|
||||
if (el.name) el.name = el.name.replace(id_regex, replacement);
|
||||
}
|
||||
function cloneMore(selector, prefix) {
|
||||
var newElement = $(selector).clone(true);
|
||||
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
|
||||
newElement.find(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function() {
|
||||
var name = $(this).attr('name').replace('-' + (total-1) + '-', '-' + total + '-');
|
||||
var id = 'id_' + name;
|
||||
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
|
||||
});
|
||||
newElement.find('label').each(function() {
|
||||
var forValue = $(this).attr('for');
|
||||
if (forValue) {
|
||||
forValue = forValue.replace('-' + (total-1) + '-', '-' + total + '-');
|
||||
$(this).attr({'for': forValue});
|
||||
}
|
||||
});
|
||||
total++;
|
||||
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
|
||||
$(selector).after(newElement);
|
||||
var conditionRow = $('.form-row:not(:last)');
|
||||
conditionRow.find('.btn.add-form-row')
|
||||
.removeClass('btn-success').addClass('btn-danger')
|
||||
.removeClass('add-form-row').addClass('remove-form-row')
|
||||
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>');
|
||||
return false;
|
||||
}
|
||||
function deleteForm(prefix, btn) {
|
||||
var total = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
|
||||
if (total > 1){
|
||||
btn.closest('.form-row').remove();
|
||||
var forms = $('.form-row');
|
||||
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
|
||||
for (var i=0, formCount=forms.length; i<formCount; i++) {
|
||||
$(forms.get(i)).find(':input').each(function() {
|
||||
updateElementIndex(this, prefix, i);
|
||||
});
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$(document).on('click', '.add-form-row', function(e){
|
||||
e.preventDefault();
|
||||
cloneMore('.form-row:last', 'form');
|
||||
return false;
|
||||
});
|
||||
$(document).on('click', '.remove-form-row', function(e){
|
||||
e.preventDefault();
|
||||
deleteForm('form', $(this));
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
45
teamsnap/templates/teamsnap/lineup/multiple_choose_2.html
Normal file
45
teamsnap/templates/teamsnap/lineup/multiple_choose_2.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ title }}{% endblock %}
|
||||
|
||||
{% csrf_token %}
|
||||
|
||||
{% block page_heading %}
|
||||
<div class="row d-inline-flex">
|
||||
<div class="col">
|
||||
Schedule
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<form method="get" action="{% url 'teamsnap_edit_multiple_lineups' team_id=team_id%}">
|
||||
{{ formset.management_form }}
|
||||
<input class="btn btn-sm btn-outline-primary text-nowrap" type="submit" value="Submit">
|
||||
{% load tz %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for form in formset %}
|
||||
{{ form.event_id.as_hidden }}
|
||||
<tr>
|
||||
<td>
|
||||
{{ form.checked }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'teamsnap_view_event' event_id=form.event.data.id team_id=request.user.profile.teamsnapsettings.managed_team.id%}">{{ form.event.data.formatted_title }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ form.event.data.start_date | localtime}}
|
||||
</td>
|
||||
<td>
|
||||
{{ form.event.data.location_name }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
100
teamsnap/templates/teamsnap/lineup/multiple_edit.html
Normal file
100
teamsnap/templates/teamsnap/lineup/multiple_edit.html
Normal file
@@ -0,0 +1,100 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} Edit Lineups {% endblock %}
|
||||
{% block page_heading %}Edit Lineups{% endblock %}
|
||||
{% block page_subheading %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{# <div class="container overflow-scroll mx-0 px-0">#}
|
||||
{# <div class="row flex-row flex-nowrap">#}
|
||||
{# {% for event_data in contexts %}#}
|
||||
{# <div class="col border-start border-end">#}
|
||||
{# <div class = "border-bottom">#}
|
||||
{# <h4>{{ event_data.event.data.formatted_title }}</h4>#}
|
||||
{# <h6 class="text-muted" >{{ event_data.data.start_date }}</h6>#}
|
||||
{# </div>#}
|
||||
{# {% include 'teamsnap/lineup/widgets/lineup.html' with formset_lineup=event_data.formset_lineup formset_bench=event_data.formset_bench event_id=event_data.event.data.id %}#}
|
||||
{# </div>#}
|
||||
{# {% endfor %}#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
<div class="container overflow-scroll">
|
||||
<div class="row flex-row flex-nowrap">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
{% for event_data in contexts %}
|
||||
<td>
|
||||
<h4>{{ event_data.event.data.formatted_title }}</h4>
|
||||
<h6 class="text-muted" >{{ event_data.data.start_date }}</h6>
|
||||
{% with 'P C 1B 2B 3B SS LF CF RF EH DH' as position_list %}
|
||||
{% for position in position_list.split %}
|
||||
<span class="position-status fw-bold small px-1" id="position-status-{{ position }}">{{ position }}</span>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-light" colspan="{{ contexts|length }}"><h4>Lineup</h4></td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% for event_data in contexts %}
|
||||
<td class="align-top">
|
||||
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=event_data.formset_lineup table_id="players-lineup" %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-light" colspan="{{ contexts|length }}"><h4>Bench</h4></td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% for event_data in contexts %}
|
||||
<td class="align-top">
|
||||
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=event_data.formset_bench table_id="players-bench" %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-light" colspan="{{ contexts|length }}"><h4>Out</h4></td>
|
||||
</tr>
|
||||
<tr>
|
||||
{% for event_data in contexts %}
|
||||
<td class="align-top">
|
||||
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=event_data.formset_out table_id="players-bench" %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{# <div class="align-content-start">#}
|
||||
{# <div class = "bg-light rounded-3 p-2">#}
|
||||
{# <div class="row">#}
|
||||
{# {% with 'P C 1B 2B 3B SS LF CF RF EH DH' as position_list %}#}
|
||||
{# {% for position in position_list.split %}#}
|
||||
{# <span class="position-status fw-bold small px-1" id="position-status-{{ position }}">{{ position }}</span>#}
|
||||
{# {% endfor %}#}
|
||||
{# {% endwith %}#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <form method="post" action="{% url 'teamsnap_submit_lineup' team_id=team_id event_id=event_id%}">#}
|
||||
{# {{ formset.management_form }}#}
|
||||
{# {% csrf_token %}#}
|
||||
|
||||
{# <h4 class="border-bottom">Lineup</h4>#}
|
||||
{# {% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_lineup table_id="players-lineup" %}#}
|
||||
{# <input class="btn btn-success" type="submit" value="Submit">#}
|
||||
{##}
|
||||
{# <h4 class="border-bottom">Bench</h4>#}
|
||||
{# {% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_bench table_id="players-bench" %}#}
|
||||
{##}
|
||||
{# <h4 class="border-bottom">Out</h4>#}
|
||||
{# {% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_out table_id="players-out" %}#}
|
||||
|
||||
{# </form>#}
|
||||
<script src="{% static 'js/Sortable.js' %}"></script>
|
||||
<script src="{% static 'teamsnap/js/lineup-table.js' %}"></script>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
28
teamsnap/templates/teamsnap/lineup/widgets/lineup.html
Normal file
28
teamsnap/templates/teamsnap/lineup/widgets/lineup.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<div>
|
||||
<div class="align-content-start">
|
||||
<div class = "bg-light rounded-3 p-2">
|
||||
{# <div class="row">#}
|
||||
{% with 'P C 1B 2B 3B SS LF CF RF EH DH' as position_list %}
|
||||
{% for position in position_list.split %}
|
||||
<span class="position-status fw-bold small px-1" id="position-status-{{ position }}">{{ position }}</span>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
{# </div>#}
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" action="{% url 'teamsnap_submit_lineup' team_id=team_id event_id=event_id%}">
|
||||
{{ formset.management_form }}
|
||||
{% csrf_token %}
|
||||
|
||||
<h4 class="border-bottom">Lineup</h4>
|
||||
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_lineup table_id="players-lineup" %}
|
||||
<input class="btn btn-success" type="submit" value="Submit">
|
||||
|
||||
<h4 class="border-bottom">Bench</h4>
|
||||
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_bench table_id="players-bench" %}
|
||||
|
||||
<h4 class="border-bottom">Out</h4>
|
||||
{% include 'teamsnap/lineup/widgets/lineup_table.html' with formset=formset_out table_id="players-out" %}
|
||||
|
||||
</form>
|
||||
</div>
|
||||
59
teamsnap/templates/teamsnap/lineup/widgets/lineup_table.html
Normal file
59
teamsnap/templates/teamsnap/lineup/widgets/lineup_table.html
Normal file
@@ -0,0 +1,59 @@
|
||||
<table class="table table-sm my-0" style="min-height: 1rem" id="table-{{ table_id }}">
|
||||
<tbody id="tbody-{{ table_id }}">
|
||||
{% for form in formset %}
|
||||
<tr data-player-id="{{ form.member.data.id }}"
|
||||
data-position="{{ form.label.value }}"
|
||||
data-order="{{ form.sequence.value }}">
|
||||
{{ form.event_lineup_entry_id.as_hidden }}
|
||||
{{ form.event_lineup_id.as_hidden }}
|
||||
{{ form.event_id.as_hidden }}
|
||||
{{ form.member_id.as_hidden }}
|
||||
{{ form.sequence.as_hidden }}
|
||||
{{ form.label.as_hidden }}
|
||||
{{ form.member_name.as_hidden }}
|
||||
<th class="col-1" id="sequence-member-{{ form.member.data.id }}">
|
||||
{{ form.sequence.value | add:"1" }}
|
||||
</th>
|
||||
<td class="col-1">
|
||||
<div class="mx-1">
|
||||
<span id="player-order-{{ form.member.id }}" class="lineup-sequence-value">
|
||||
{% if form.order.value > 0 %} {{ form.order.value | add:"1" }} {% endif %}
|
||||
</span>
|
||||
|
||||
<span id="player-availability-{{ form.member.id }}" class="member-availability-status small">
|
||||
{% if form.availability.data.status_code == 2 %}
|
||||
<i class="bi bi-question-circle-fill text-info"></i>
|
||||
{% elif form.availability.data.status_code == 1 %}
|
||||
<i class="bi bi-check-circle-fill text-success"></i>
|
||||
{% elif form.availability.data.status_code == 0 %}
|
||||
<i class="bi bi-x-circle-fill text-danger"></i>
|
||||
{% else %}
|
||||
<i class="bi bi-question-circle"></i>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<th class="">
|
||||
<div class="text-nowrap">
|
||||
<span class="d-none d-md-inline-block">
|
||||
{{ form.member.data.first_name }}
|
||||
</span>
|
||||
{{ form.member.data.last_name }}
|
||||
<span class="small text-muted fw-light d-none d-lg-inline-block">
|
||||
#{{ form.member.data.jersey_number }}
|
||||
</span>
|
||||
</div>
|
||||
{# <br><code><small>{{ form.statline }}</small></code>#}
|
||||
</th>
|
||||
<td class="col-2">
|
||||
{{ form.label }}
|
||||
</td>
|
||||
<td class="col-1 drag-handle">
|
||||
<i class="bi bi-grip-vertical text-secondary"></i>
|
||||
</td>
|
||||
{# <td>{{ form.instance.position }}</td>#}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
22
teamsnap/templates/teamsnap/location/view.html
Normal file
22
teamsnap/templates/teamsnap/location/view.html
Normal file
@@ -0,0 +1,22 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ location.data.name }}{% endblock %}
|
||||
{% block page_heading %}{{ location.data.name }}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for key, value in location.data.items %}
|
||||
<tr>
|
||||
<th scope="col">
|
||||
{{ key }}
|
||||
</th>
|
||||
<td>
|
||||
{{ value }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
22
teamsnap/templates/teamsnap/opponent.html
Normal file
22
teamsnap/templates/teamsnap/opponent.html
Normal file
@@ -0,0 +1,22 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ opponent.data.name }}{% endblock %}
|
||||
{% block page_heading %}{{ opponent.data.name }}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for key, value in opponent.data.items %}
|
||||
<tr>
|
||||
<th scope="col">
|
||||
{{ key }}
|
||||
</th>
|
||||
<td>
|
||||
{{ value }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
47
teamsnap/templates/teamsnap/schedule.html
Normal file
47
teamsnap/templates/teamsnap/schedule.html
Normal file
@@ -0,0 +1,47 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ title }}{% endblock %}
|
||||
{% block page_heading %}
|
||||
<div class="row d-inline-flex">
|
||||
<div class="col">
|
||||
Schedule
|
||||
</div>
|
||||
<div hidden class="col">
|
||||
<div class="container m-2">
|
||||
<div class="container m-2">
|
||||
<div class="btn-group">
|
||||
<form action="">
|
||||
<a class="btn btn-sm btn-outline-primary text-nowrap" href="{% url 'teamsnap_schedule' team_id=team_id%}?filters=no_past">No Past Events</a>
|
||||
<button class="btn btn-sm btn-outline-primary text-nowrap">Games Only</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% load tz %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for event in events %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'teamsnap_view_event' event_id=event.data.id team_id=request.user.profile.teamsnapsettings.managed_team.id%}">{{ event.data.formatted_title }}</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ event.data.start_date | localtime}}
|
||||
</td>
|
||||
<td>
|
||||
{{ event.data.location_name }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
137
teamsnap/templates/teamsnap/view_event.html
Normal file
137
teamsnap/templates/teamsnap/view_event.html
Normal file
@@ -0,0 +1,137 @@
|
||||
{% extends "base.html" %}{% load static %}
|
||||
{% block title %} {{ event.data.formatted_title }}{% endblock %}
|
||||
{% block page_heading %}{{ event.data.formatted_title }}{% endblock %}
|
||||
{% block page_subheading %}{{ event.data.start_date }}, {{ event.data.location_name }}{% endblock %}
|
||||
{% block content %}
|
||||
<div class="table-responsive">
|
||||
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
Date
|
||||
</th>
|
||||
<td>
|
||||
{{ event.data.start_date }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
Opponent
|
||||
</th>
|
||||
<td>
|
||||
<a href="{% url 'teamsnap_opponent' team_id=request.user.profile.teamsnapsettings.managed_team.id id=event.data.opponent_id %}">{{ event.data.opponent_name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">
|
||||
Location
|
||||
</th>
|
||||
<td>
|
||||
<a href="{% url 'teamsnap_location' team_id=request.user.profile.teamsnapsettings.managed_team.id id=event.data.location_id %}">{{ event.data.location_name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h3>Availabilities</h3>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# <th scope="row">#}
|
||||
{# <td>Status</td>#}
|
||||
{# <td>Last</td>#}
|
||||
{# <td>First</td>#}
|
||||
{# </th>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="col" class="col-1">
|
||||
<i class="bi bi-check-circle-fill text-success"></i>
|
||||
</th>
|
||||
<td>
|
||||
{{ availability_summary.data.player_going_count }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="col" class="col-1">
|
||||
<i class="bi bi-question-circle-fill text-info"></i>
|
||||
</th>
|
||||
<td>
|
||||
{{ availability_summary.data.player_maybe_count }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="col" class="col-1">
|
||||
<i class="bi bi-x-circle-fill text-danger"></i>
|
||||
</th>
|
||||
<td>
|
||||
{{ availability_summary.data.player_not_going_count }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="col" class="col-1">
|
||||
<i class="bi bi-question-circle"></i>
|
||||
</th>
|
||||
<td>
|
||||
{{ availability_summary.data.player_unknown_count }}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="">
|
||||
<h3>Lineup Entries</h3>
|
||||
<a class="btn btn-primary btn-sm" href="{% url 'teamsnap_edit_lineup' event_id=event.data.id team_id=request.user.profile.teamsnapsettings.managed_team.id%}" role="button">Edit</a>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
{# <thead>#}
|
||||
{# <th scope="row">#}
|
||||
{# <td>Status</td>#}
|
||||
{# <td>Last</td>#}
|
||||
{# <td>First</td>#}
|
||||
{# </th>#}
|
||||
{# </thead>#}
|
||||
<tbody>
|
||||
{% for lineup_entry in lineup_entries %}
|
||||
<tr>
|
||||
<td class="col-1">
|
||||
{{ lineup_entry.data.sequence }}
|
||||
</td>
|
||||
<td>
|
||||
{{ lineup_entry.data.member_name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ lineup_entry.data.label }}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<h3>Functions</h3>
|
||||
<div class="">
|
||||
<form method="get" action="{% url "teamsnap_image_generator_generate" team_id=request.user.profile.teamsnapsettings.managed_team.id event_id=event.data.id %}">
|
||||
<select hidden class="form-select" name="game_id" id="game_id">
|
||||
<optgroup label="Events">
|
||||
<option value="" disabled="disabled">Select an event...</option>
|
||||
<option selected value="{{event.data.id}}">{{event.data.formatted_title}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<input hidden class="form-check-input" type="radio" name="background" id="backgroundLocation" checked value="location">
|
||||
<input hidden class="form-check-input" type="radio" name="dimensions" id="square" checked value="1080x1080">
|
||||
<button type="submit" class="btn btn-primary btn-block"><i class="bi bi-instagram"></i></button>
|
||||
</form>
|
||||
<a class="btn btn-primary" href="{% url "teamsnap_image_generator" team_id=request.user.profile.teamsnapsettings.managed_team.id event_id=event.data.id %}" role="button"><div class="d-inline-block"><i class="bi bi-instagram"></i> <i class="bi bi-three-dots"></i></div></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -6,8 +6,19 @@ from functools import partial
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.home, name='teamsnap home'),
|
||||
path('', views.home, name='teamsnap_home'),
|
||||
path('edit/event/<int:id>', views.edit_event, name='teamsnap edit event'),
|
||||
path('sync/download', views.sync_from_teamsnap, name="sync from teamsnap"),
|
||||
path('import/', views.import_teamsnap, name="import")
|
||||
path('import/', views.import_teamsnap, name="import"),
|
||||
|
||||
path('<int:team_id>/schedule/', views.schedule, name='teamsnap_schedule'),
|
||||
path('<int:team_id>/schedule/view_event/<int:event_id>', views.event, name='teamsnap_view_event'),
|
||||
path('<int:team_id>/opponent/view/<int:id>', views.opponent, name='teamsnap_opponent'),
|
||||
path('<int:team_id>/location/view/<int:id>', views.location, name='teamsnap_location'),
|
||||
path('<int:team_id>/event/<int:event_id>/edit_lineup/', views.edit_lineup, name='teamsnap_edit_lineup'),
|
||||
path('<int:team_id>/event/<int:event_id>/submit_lineup/', views.submit_lineup, name='teamsnap_submit_lineup'),
|
||||
path('<int:team_id>/event/<int:event_id>/image_generator/', views.image_generator, name='teamsnap_image_generator'),
|
||||
path('<int:team_id>/event/<int:event_id>/image_generator/generate', views.get_matchup_image, name='teamsnap_image_generator_generate'),
|
||||
path('<int:team_id>/multievent/edit_lineups', views.edit_multiple_lineups, name='teamsnap_edit_multiple_lineups'),
|
||||
path('<int:team_id>/multievent/choose', views.multi_lineup_choose, name='teamsnap_choose_multiple_lineups')
|
||||
]
|
||||
331
teamsnap/utils/gen_image.py
Normal file
331
teamsnap/utils/gen_image.py
Normal file
@@ -0,0 +1,331 @@
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
from PIL import ImageFilter, ImageFont
|
||||
from pathlib import Path
|
||||
import os
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
from typing import List
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
# image_directory = 'input/images/logos-bw/{filename}.{ext}'
|
||||
|
||||
# font_regular_path = "input/fonts/DINAlternate-Bold.ttf"
|
||||
# font_condensed_path = "input/fonts/DINCondensed-Bold.ttf"
|
||||
font_regular_path = "benchcoachproject/static/teamsnap/ig/fonts/ScalaSans-BoldLF.otf"
|
||||
font_condensed_path = "benchcoachproject/static/teamsnap/ig/fonts/ScalaSans-BoldLF.otf"
|
||||
|
||||
@dataclass
|
||||
class Team:
|
||||
name: str
|
||||
winlosstie: List[int] = None
|
||||
image_directory: str = '../input/images/logos-bw/{filename}.{ext}'
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.name.lower().replace(' ', '-')
|
||||
|
||||
@property
|
||||
def image(self):
|
||||
path = self.image_directory.format(filename=self.id, ext="png")
|
||||
if os.path.isfile(path):
|
||||
return path
|
||||
else:
|
||||
return None
|
||||
|
||||
@dataclass
|
||||
class Location:
|
||||
name: str
|
||||
address1: str = ""
|
||||
address2: str = ""
|
||||
image_directory: str = 'benchcoachproject/static/teamsnap/ig/locations/{filename}.{ext}'
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.name.lower().replace(' ', '-')
|
||||
|
||||
@property
|
||||
def image(self):
|
||||
path = self.image_directory.format(filename=self.id, ext="png")
|
||||
if os.path.isfile(path):
|
||||
return path
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return ",".join([self.address1,self.address2])
|
||||
|
||||
args = {
|
||||
"team_fave" : Team("Hounds"),
|
||||
"team_opponent" : Team("Trojans"),
|
||||
"home": False,
|
||||
"date" : "2021-05-08 12:30 pm",
|
||||
"location" : Location("Maywood", image_directory="benchcoachproject/static/teamsnap/ig/locations/maywood.{ext}"),
|
||||
"runs_for": 8,
|
||||
"runs_against": 9
|
||||
}
|
||||
|
||||
def gen_image (team_fave, team_opponent, date, location=None,
|
||||
location_name = None,
|
||||
home=False,
|
||||
background='location',
|
||||
address = None,
|
||||
width = 1080,
|
||||
height = 1080,
|
||||
*kwargs,
|
||||
**args
|
||||
):
|
||||
if not isinstance(date, datetime):
|
||||
# date = parser.parse(date)
|
||||
# date = date.astimezone(ZoneInfo("America/Chicago"))
|
||||
pass
|
||||
|
||||
if location.image and background == 'location':
|
||||
background_image = Image.open(location.image).copy()
|
||||
background_image = background_image.resize((width, height))
|
||||
# background_image = background_image.filter(ImageFilter.GaussianBlur(radius=5))
|
||||
background_image = background_image.convert("RGBA")
|
||||
elif background == 'transparent':
|
||||
background_image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
|
||||
else:
|
||||
background_image = Image.new('RGBA', (width, height), (50, 55, 102))
|
||||
|
||||
title_images = []
|
||||
for team in [team_fave, team_opponent]:
|
||||
if team.image:
|
||||
title_images.append(Image.open(team.image).copy())
|
||||
else:
|
||||
title_images.append(Image.new('RGBA', (1080, 1080)))
|
||||
|
||||
title_image_left = title_images[0]
|
||||
title_image_right = title_images[1]
|
||||
|
||||
# Make a blank image for the rectangle, initialized to a completely
|
||||
# transparent color.
|
||||
tmp = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
|
||||
|
||||
# Create a drawing context for it.
|
||||
draw = ImageDraw.Draw(tmp)
|
||||
|
||||
# section margin describes the margin of the section rectangles from the sides of the image
|
||||
section_margin_pct = .05
|
||||
llx = int(section_margin_pct * background_image.size[0])
|
||||
urx = int((1 - section_margin_pct) * background_image.size[0])
|
||||
lly = int((1 - section_margin_pct) * background_image.size[1])
|
||||
ury = int(.50 * background_image.size[1])
|
||||
|
||||
lly2 = int(.49 * background_image.size[1])
|
||||
ury2 = int(.05 * background_image.size[1])
|
||||
|
||||
section_info = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-tan", ext=".png")))
|
||||
section_info_draw = ImageDraw.Draw(section_info)
|
||||
|
||||
section_title = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-green", ext=".png")))
|
||||
section_title_draw = ImageDraw.Draw(section_title)
|
||||
|
||||
# First line: Date
|
||||
font = ImageFont.truetype(font_regular_path, 62)
|
||||
text = "{:%a, %B %-d %-I:%M %p}".format(date).upper()
|
||||
# text = date
|
||||
text_size = draw.textsize(text, font)
|
||||
loc = (
|
||||
1050,
|
||||
280
|
||||
)
|
||||
section_info_draw.text(loc, text, (14,42,28), font=font, anchor="ra")
|
||||
|
||||
# Second line: Venue
|
||||
font = ImageFont.truetype(font_condensed_path, 34)
|
||||
if not location_name:
|
||||
text = location.name.upper()
|
||||
else:
|
||||
text = location_name.upper()
|
||||
text_size = section_info_draw.textsize(text, font)
|
||||
loc = (
|
||||
1050,
|
||||
355
|
||||
)
|
||||
section_info_draw.text(loc, text, (14,42,28), font=font, anchor="ra")
|
||||
|
||||
font = ImageFont.truetype(font_regular_path, 80)
|
||||
if home:
|
||||
text = "VS"
|
||||
else:
|
||||
text = "AT"
|
||||
text_size = section_title_draw.textsize(text, font)
|
||||
loc = (
|
||||
540,
|
||||
120
|
||||
)
|
||||
color = (255, 255, 255)
|
||||
section_title_draw.text(loc, text, color, font=font, anchor="mm")
|
||||
|
||||
# Alpha composite the two images together.
|
||||
background_image = Image.alpha_composite(background_image, tmp)
|
||||
|
||||
# Title Image Left
|
||||
title_image_left.thumbnail([350, 350])
|
||||
loc = (
|
||||
50, -50
|
||||
)
|
||||
section_title.paste(title_image_left, loc, title_image_left)
|
||||
|
||||
# Title Image Right
|
||||
title_image_right.thumbnail([350, 350])
|
||||
loc = (
|
||||
650, -50
|
||||
)
|
||||
section_title.paste(title_image_right, loc, title_image_right)
|
||||
|
||||
# background_image.paste(section_info, (llx, ury), section_info)
|
||||
# background_image.paste(section_title, (llx, ury2), section_title)
|
||||
section_title.paste(section_info,(0,0),section_info)
|
||||
section_title.thumbnail([800, 800])
|
||||
|
||||
if background=="badge":
|
||||
return section_title
|
||||
|
||||
background_image.paste(section_title,(
|
||||
int((background_image.size[0]-section_title.size[0])/2),
|
||||
height - 360
|
||||
),section_title)
|
||||
|
||||
return background_image
|
||||
|
||||
def gen_results_image (team_fave, team_opponent, date,
|
||||
location=None,
|
||||
location_name = None,
|
||||
home=False,
|
||||
background='location',
|
||||
address = None,
|
||||
width = 1080,
|
||||
height = 1080,
|
||||
runs_for=0,
|
||||
runs_against=0,
|
||||
*kwargs,
|
||||
**args
|
||||
):
|
||||
if not isinstance(date, datetime):
|
||||
# date = parser.parse(date)
|
||||
# date = date.astimezone(ZoneInfo("America/Chicago"))
|
||||
pass
|
||||
|
||||
if location.image and background == 'location':
|
||||
background_image = Image.open(location.image).copy()
|
||||
background_image = background_image.resize((width, height))
|
||||
# background_image = background_image.filter(ImageFilter.GaussianBlur(radius=5))
|
||||
background_image = background_image.convert("RGBA")
|
||||
elif background == 'transparent':
|
||||
background_image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
|
||||
else:
|
||||
background_image = Image.new('RGBA', (width, height), (50, 55, 102))
|
||||
|
||||
title_images = []
|
||||
for team in [team_fave, team_opponent]:
|
||||
if team.image:
|
||||
title_images.append(Image.open(team.image).copy())
|
||||
else:
|
||||
title_images.append(Image.new('RGBA', (1080, 1080)))
|
||||
|
||||
title_image_left = title_images[0]
|
||||
title_image_right = title_images[1]
|
||||
|
||||
# Make a blank image for the rectangle, initialized to a completely
|
||||
# transparent color.
|
||||
tmp = Image.new('RGBA', background_image.size, (0, 0, 0, 0))
|
||||
|
||||
# Create a drawing context for it.
|
||||
draw = ImageDraw.Draw(tmp)
|
||||
|
||||
# section margin describes the margin of the section rectangles from the sides of the image
|
||||
section_margin_pct = .05
|
||||
llx = int(section_margin_pct * background_image.size[0])
|
||||
urx = int((1 - section_margin_pct) * background_image.size[0])
|
||||
lly = int((1 - section_margin_pct) * background_image.size[1])
|
||||
ury = int(.50 * background_image.size[1])
|
||||
|
||||
lly2 = int(.49 * background_image.size[1])
|
||||
ury2 = int(.05 * background_image.size[1])
|
||||
|
||||
#todo fix path
|
||||
section_info = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-tan", ext=".png")))
|
||||
section_info_draw = ImageDraw.Draw(section_info)
|
||||
|
||||
section_title = Image.open(Path('benchcoachproject/static/teamsnap/ig/graphics/{name}{ext}'.format(name="sign-green", ext=".png")))
|
||||
section_title_draw = ImageDraw.Draw(section_title)
|
||||
|
||||
# First line: Results
|
||||
loc = (
|
||||
1050,
|
||||
265
|
||||
)
|
||||
if runs_for > runs_against:
|
||||
result_letter = "W"
|
||||
elif runs_for < runs_against:
|
||||
result_letter = "L"
|
||||
elif runs_for == runs_against:
|
||||
result_letter = "T"
|
||||
font = ImageFont.truetype(font_regular_path, 100)
|
||||
section_info_draw.text(loc, f"FINAL: {result_letter} {runs_for}-{runs_against}", (14,42,28), font=font, anchor="ra")
|
||||
|
||||
# Second line: Date
|
||||
text = "{:%a, %B %-d %-I:%M %p}".format(date).upper()
|
||||
# text = date
|
||||
font = ImageFont.truetype(font_condensed_path, 34)
|
||||
text_size = section_info_draw.textsize(text, font)
|
||||
loc = (
|
||||
1050,
|
||||
355
|
||||
)
|
||||
section_info_draw.text(loc, text, (14,42,28), font=font, anchor="ra")
|
||||
|
||||
font = ImageFont.truetype(font_regular_path, 80)
|
||||
if home:
|
||||
text = "VS"
|
||||
else:
|
||||
text = "AT"
|
||||
text_size = section_title_draw.textsize(text, font)
|
||||
loc = (
|
||||
540,
|
||||
120
|
||||
)
|
||||
color = (255, 255, 255)
|
||||
section_title_draw.text(loc, text, color, font=font, anchor="mm")
|
||||
|
||||
# Alpha composite the two images together.
|
||||
background_image = Image.alpha_composite(background_image, tmp)
|
||||
|
||||
# Title Image Left
|
||||
title_image_left.thumbnail([350, 350])
|
||||
loc = (
|
||||
50, -50
|
||||
)
|
||||
section_title.paste(title_image_left, loc, title_image_left)
|
||||
|
||||
# Title Image Right
|
||||
title_image_right.thumbnail([350, 350])
|
||||
loc = (
|
||||
650, -50
|
||||
)
|
||||
section_title.paste(title_image_right, loc, title_image_right)
|
||||
|
||||
# background_image.paste(section_info, (llx, ury), section_info)
|
||||
# background_image.paste(section_title, (llx, ury2), section_title)
|
||||
section_title.paste(section_info,(0,0),section_info)
|
||||
section_title.thumbnail([800, 800])
|
||||
|
||||
if background=="badge":
|
||||
return section_title
|
||||
|
||||
background_image.paste(section_title,(
|
||||
int((background_image.size[0]-section_title.size[0])/2),
|
||||
height - 360
|
||||
),section_title)
|
||||
|
||||
# background_image.show()
|
||||
|
||||
return background_image
|
||||
|
||||
# gen_results_image(**args)
|
||||
@@ -3,7 +3,8 @@ from typing import List, Tuple
|
||||
|
||||
import benchcoach.models
|
||||
from benchcoach.models import BenchcoachModel, Availability, Player, Team, Positioning, Event, Venue
|
||||
from teamsnap.teamsnap.api import TeamSnap
|
||||
from pyteamsnap.api import TeamSnap
|
||||
import pyteamsnap
|
||||
import teamsnap.models
|
||||
from django.db.models import QuerySet
|
||||
|
||||
@@ -50,14 +51,14 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
}
|
||||
|
||||
teamsnapmodel_to_apiobject = {
|
||||
teamsnap.models.Availability: teamsnap.teamsnap.api.Availability,
|
||||
teamsnap.models.Event: teamsnap.teamsnap.api.Event,
|
||||
# teamsnap.models.LineupEntry:teamsnap.teamsnap.api.LineupEntry, # Not implemented Yet
|
||||
teamsnap.models.Location: teamsnap.teamsnap.api.Location,
|
||||
teamsnap.models.Member: teamsnap.teamsnap.api.Member,
|
||||
teamsnap.models.Opponent: teamsnap.teamsnap.api.Opponent,
|
||||
teamsnap.models.Team: teamsnap.teamsnap.api.Team,
|
||||
# teamsnap.models.User:teamsnap.teamsnap.api.User # Not implemented yet
|
||||
teamsnap.models.Availability: pyteamsnap.api.Availability,
|
||||
teamsnap.models.Event: pyteamsnap.api.Event,
|
||||
# teamsnap.models.LineupEntry:pyteamsnap.api.LineupEntry, # Not implemented Yet
|
||||
teamsnap.models.Location: pyteamsnap.api.Location,
|
||||
teamsnap.models.Member: pyteamsnap.api.Member,
|
||||
teamsnap.models.Opponent: pyteamsnap.api.Opponent,
|
||||
teamsnap.models.Team: pyteamsnap.api.Team,
|
||||
# teamsnap.models.User:pyteamsnap.api.User # Not implemented yet
|
||||
}
|
||||
|
||||
apiobject_to_teamsnapmodel = {v:k for k,v in teamsnapmodel_to_apiobject.items()}
|
||||
@@ -104,14 +105,14 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
}
|
||||
|
||||
teamsnapmodel_to_apiobject = {
|
||||
teamsnap.models.Availability: teamsnap.teamsnap.api.Availability,
|
||||
teamsnap.models.Event: teamsnap.teamsnap.api.Event,
|
||||
# teamsnap.models.LineupEntry:teamsnap.teamsnap.api.LineupEntry, # Not implemented Yet
|
||||
teamsnap.models.Location: teamsnap.teamsnap.api.Location,
|
||||
teamsnap.models.Member: teamsnap.teamsnap.api.Member,
|
||||
teamsnap.models.Opponent: teamsnap.teamsnap.api.Opponent,
|
||||
teamsnap.models.Team: teamsnap.teamsnap.api.Team,
|
||||
# teamsnap.models.User:teamsnap.teamsnap.api.User # Not implemented yet
|
||||
teamsnap.models.Availability: pyteamsnap.api.Availability,
|
||||
teamsnap.models.Event: pyteamsnap.api.Event,
|
||||
# teamsnap.models.LineupEntry:pyteamsnap.api.LineupEntry, # Not implemented Yet
|
||||
teamsnap.models.Location: pyteamsnap.api.Location,
|
||||
teamsnap.models.Member: pyteamsnap.api.Member,
|
||||
teamsnap.models.Opponent: pyteamsnap.api.Opponent,
|
||||
teamsnap.models.Team: pyteamsnap.api.Team,
|
||||
# teamsnap.models.User:pyteamsnap.api.User # Not implemented yet
|
||||
}
|
||||
|
||||
if isinstance(benchcoach_instance, benchcoach.models.Team):
|
||||
@@ -128,9 +129,9 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
r = self._update_teamsnapdb_to_benchcoachdb(teamsnap_instance, benchcoach_instance)
|
||||
return r
|
||||
|
||||
def _update_from_teamsnapdata(self, teamsnap_instance:teamsnap.models.TeamsnapBaseModel, teamsnap_data: teamsnap.teamsnap.api.ApiObject) -> teamsnap.models.TeamsnapBaseModel:
|
||||
def _update_from_teamsnapdata(self, teamsnap_instance:teamsnap.models.TeamsnapBaseModel, teamsnap_data: pyteamsnap.api.ApiObject) -> teamsnap.models.TeamsnapBaseModel:
|
||||
''''''
|
||||
if isinstance(teamsnap_data, teamsnap.teamsnap.api.ApiObject):
|
||||
if isinstance(teamsnap_data, pyteamsnap.api.ApiObject):
|
||||
teamsnap_data = teamsnap_data.data
|
||||
else:
|
||||
raise TypeError
|
||||
@@ -390,7 +391,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
r['team'] = []
|
||||
|
||||
# Search API for objects belonging to currently managed team, and iterate
|
||||
for teamsnap_data in teamsnap.teamsnap.api.Team.search(client=self.client, id=self.managed_teamsnap_team_id):
|
||||
for teamsnap_data in pyteamsnap.api.Team.search(client=self.client, id=self.managed_teamsnap_team_id):
|
||||
# check if TeamSnap ID already exists in the Teamsnap DB.
|
||||
if teamsnap.models.Team.objects.filter(id=teamsnap_data.data['id']):
|
||||
teamsnap_instance = teamsnap.models.Team.objects.filter(id=teamsnap_data.data['id']).first()
|
||||
@@ -417,7 +418,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
# Opponents from teamsnap go to the BenchCoach "Team" database.
|
||||
# Dependent on Team. These objects need to be available to attach as related objects or the functions
|
||||
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
|
||||
for teamsnap_data in teamsnap.teamsnap.api.Opponent.search(**kwargs):
|
||||
for teamsnap_data in pyteamsnap.api.Opponent.search(**kwargs):
|
||||
if teamsnap.models.Opponent.objects.filter(id=teamsnap_data.data['id']):
|
||||
teamsnap_instance = teamsnap.models.Opponent.objects.filter(id=teamsnap_data.data['id']).first()
|
||||
benchcoach_instance = teamsnap_instance.benchcoach_object
|
||||
@@ -435,7 +436,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
# Dependent on Team. These objects need to be available to attach as related objects or the functions
|
||||
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
|
||||
r['location'] = []
|
||||
for teamsnap_data in teamsnap.teamsnap.api.Location.search(**kwargs):
|
||||
for teamsnap_data in pyteamsnap.api.Location.search(**kwargs):
|
||||
if teamsnap.models.Location.objects.filter(id=teamsnap_data.data['id']):
|
||||
teamsnap_instance = teamsnap.models.Location.objects.filter(id=teamsnap_data.data['id']).first()
|
||||
benchcoach_instance = teamsnap_instance.benchcoach_object
|
||||
@@ -455,7 +456,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
|
||||
r['member'] = []
|
||||
# Search API for members to import. Note: Non players are not included in sync.
|
||||
for teamsnap_data in teamsnap.teamsnap.api.Member.search(**kwargs,
|
||||
for teamsnap_data in pyteamsnap.api.Member.search(**kwargs,
|
||||
is_non_player = False
|
||||
):
|
||||
if teamsnap_data.data['is_non_player'] == True:
|
||||
@@ -478,7 +479,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
# Dependent on Team, Opponent, Location. These objects need to be available to attach as related objects or the functions
|
||||
# self._update_from teamsnapdata and self.update_teamsnapdb_to_benchcoachdb may fail.
|
||||
r['event'] = []
|
||||
for teamsnap_data in teamsnap.teamsnap.api.Event.search(**kwargs):
|
||||
for teamsnap_data in pyteamsnap.api.Event.search(**kwargs):
|
||||
if teamsnap.models.Event.objects.filter(id=teamsnap_data.data['id']):
|
||||
teamsnap_instance = teamsnap.models.Event.objects.filter(id=teamsnap_data.data['id']).first()
|
||||
benchcoach_instance = teamsnap_instance.benchcoach_object
|
||||
@@ -504,7 +505,7 @@ class TeamsnapSyncEngine(AbstractSyncEngine):
|
||||
|
||||
# Search API for members to import. Note: Non players are not included in sync.
|
||||
player_ids = [member.id for member in teamsnap.models.Member.objects.filter(is_non_player=False)]
|
||||
for teamsnap_data in teamsnap.teamsnap.api.Availability.search(**kwargs,
|
||||
for teamsnap_data in pyteamsnap.api.Availability.search(**kwargs,
|
||||
member_id=",".join(player_ids)
|
||||
):
|
||||
if teamsnap.models.Availability.objects.filter(id=teamsnap_data.data['id']):
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import operator
|
||||
import time
|
||||
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
from .models import User, Member, Team, Event, Location, LineupEntry, Opponent, Availability
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, HttpResponseNotAllowed
|
||||
import benchcoach.models
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from .utils.teamsnap_sync_engine import TeamsnapSyncEngine
|
||||
from django.templatetags.static import static
|
||||
import datetime
|
||||
|
||||
def edit_event(request, id):
|
||||
'''
|
||||
@@ -112,6 +117,7 @@ def sync_from_teamsnap(request, object_name=None, object_id=None):
|
||||
return HttpResponse(404)
|
||||
|
||||
|
||||
|
||||
def import_teamsnap(request):
|
||||
TEAM_ID = request.user.profile.teamsnapsettings.managed_team.id
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
@@ -127,5 +133,437 @@ def import_teamsnap(request):
|
||||
|
||||
return redirect('teamsnap home')
|
||||
|
||||
def schedule(request, team_id):
|
||||
TEAM_ID = team_id
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
no_past = bool(request.GET.get('no_past', 0))
|
||||
games_only = bool(request.GET.get('games_only',0))
|
||||
from pyteamsnap.api import TeamSnap, Event, Location, Opponent
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(.5)
|
||||
ts_events = Event.search(client, team_id=TEAM_ID)
|
||||
if no_past:
|
||||
ts_events = [e for e in ts_events if e.data['start_date'] > datetime.datetime.now(datetime.timezone.utc)]
|
||||
if games_only:
|
||||
ts_events = [e for e in ts_events if e.data['is_game']]
|
||||
ts_events = {e.data['id']:e for e in ts_events}
|
||||
# ts_opponents = {o.data['id']:o for o in Opponent.search(client, team_id=TEAM_ID)}
|
||||
# ts_locations = {l.data['id']:l for l in Location.search(client, team_id=TEAM_ID)}
|
||||
# for event in ts_events:
|
||||
|
||||
|
||||
pass
|
||||
return render(request, "teamsnap/schedule.html", context={"events":ts_events.values(), "team_id":team_id})
|
||||
|
||||
def event(request, event_id, team_id):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
|
||||
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(0.5)
|
||||
ts_bulkload = client.bulk_load(team_id=team_id,
|
||||
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
|
||||
event__id=event_id)
|
||||
ts_event = [i for i in ts_bulkload if isinstance(i, Event)][0]
|
||||
# ts_availabilities = Availability.search(client, event_id=ts_event.data['id'])
|
||||
ts_availability_summary = \
|
||||
[i for i in ts_bulkload if isinstance(i, AvailabilitySummary) and i.data['event_id'] == event_id][0]
|
||||
ts_lineup_entries = [i for i in ts_bulkload if isinstance(i, EventLineupEntry) and i.data['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}
|
||||
# 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 = []
|
||||
|
||||
return render(request, "teamsnap/view_event.html", context={
|
||||
"availability_summary":ts_availability_summary,
|
||||
"event":ts_event,
|
||||
"availablities":[],
|
||||
"lineup_entries": ts_lineup_entries,
|
||||
})
|
||||
|
||||
def location(request, id, team_id):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
|
||||
from pyteamsnap.api import TeamSnap, Location
|
||||
client = TeamSnap(token=TOKEN)
|
||||
return render(request, "teamsnap/location/view.html", context={"location": Location.get(client, id=id)})
|
||||
pass
|
||||
|
||||
def opponent(request, id):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
|
||||
from pyteamsnap.api import TeamSnap, Opponent
|
||||
time.sleep(0.5)
|
||||
client = TeamSnap(token=TOKEN)
|
||||
return render(request, "teamsnap/opponent.html", context={"opponent": Opponent.get(client, id=id)})
|
||||
pass
|
||||
|
||||
def edit_lineup(request, event_id, team_id):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
|
||||
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary, Opponent
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(0.5)
|
||||
|
||||
ts_bulkload = client.bulk_load(team_id=team_id,
|
||||
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
|
||||
event__id=event_id)
|
||||
ts_event = [i for i in ts_bulkload if isinstance(i, Event)][0]
|
||||
ts_availabilities = Availability.search(client, event_id=ts_event.data['id'])
|
||||
ts_availability_summary = \
|
||||
[i for i in ts_bulkload if isinstance(i, AvailabilitySummary) and i.data['event_id'] == event_id][0]
|
||||
ts_lineup_entries = [i for i in ts_bulkload if isinstance(i, EventLineupEntry) and i.data['event_id'] == event_id]
|
||||
|
||||
if ts_lineup_entries:
|
||||
ts_lineup = EventLineup.get(client, id=ts_lineup_entries[0].data['event_lineup_id'])
|
||||
else:
|
||||
ts_lineup = EventLineup.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}
|
||||
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 member in ts_members:
|
||||
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, # No Response
|
||||
0:2, # No
|
||||
2:1, # Maybe
|
||||
1:0 # Yes
|
||||
|
||||
}.get(d['availability'].get('status_code')),
|
||||
d['member'].get('last_name'))
|
||||
)
|
||||
|
||||
|
||||
from teamsnap.forms import LineupEntryFormset, LineupEntryForm
|
||||
|
||||
formset = LineupEntryFormset(
|
||||
initial=[
|
||||
{
|
||||
"event_lineup_entry_id" : member['lineup_entry'].get('id'),
|
||||
"event_lineup_id" : member['lineup_entry'].get('event_lineup_id'),
|
||||
"event_id": event_id,
|
||||
"member_id" : member['member']['id'],
|
||||
"sequence" : member['lineup_entry'].get('sequence'),
|
||||
"label" : member['lineup_entry'].get('label'),
|
||||
}
|
||||
for member in members
|
||||
]
|
||||
)
|
||||
|
||||
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_lineup = [form for form in formset if form.initial.get('event_lineup_entry_id')]
|
||||
formset_lineup = sorted(
|
||||
formset_lineup,
|
||||
key=lambda d: d.initial.get('sequence',100)
|
||||
)
|
||||
formset_bench = [form for form in formset if
|
||||
form not in formset_lineup and
|
||||
form.availability.data['status_code'] in [2, 1]
|
||||
]
|
||||
formset_out = [form for form in formset if
|
||||
form not in formset_lineup and
|
||||
form not in formset_bench and
|
||||
not form.member.data['is_non_player']
|
||||
]
|
||||
|
||||
return render(request, "teamsnap/lineup/edit.html", context={
|
||||
"team_id": team_id,
|
||||
"event_id": event_id,
|
||||
"event": ts_event,
|
||||
"formset": formset,
|
||||
"formset_lineup":formset_lineup,
|
||||
"formset_bench": formset_bench,
|
||||
"formset_out": formset_out,
|
||||
"lineup": ts_lineup
|
||||
})
|
||||
|
||||
def edit_multiple_lineups(request, team_id):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
from django.forms import formset_factory
|
||||
from teamsnap.forms import EventChooseForm
|
||||
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary, Opponent
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(0.5)
|
||||
|
||||
ts_events = Event.search(client, team_id=team_id)
|
||||
EventChooseFormset = formset_factory(EventChooseForm)
|
||||
formset = EventChooseFormset(request.GET)
|
||||
choices = [(e.data['id'], e.data['formatted_title']) for e in ts_events]
|
||||
|
||||
for form in formset:
|
||||
form.fields['event_id'].choices = choices
|
||||
|
||||
if formset.is_valid():
|
||||
event_ids = [f.cleaned_data['event_id'] for f in formset]
|
||||
else:
|
||||
event_ids = request.GET.get("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]
|
||||
formsets_lineup = []
|
||||
formsets_bench = []
|
||||
formsets = []
|
||||
events = []
|
||||
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_availability_summary = \
|
||||
[i for i in ts_bulkload if isinstance(i, AvailabilitySummary) and i.data['event_id'] == event_id][0]
|
||||
ts_lineup_entries = [i for i in ts_bulkload if isinstance(i, EventLineupEntry) and i.data['event_id'] == event_id]
|
||||
|
||||
if ts_lineup_entries:
|
||||
ts_lineup = EventLineup.get(client, id=ts_lineup_entries[0].data['event_lineup_id'])
|
||||
else:
|
||||
ts_lineup = EventLineup.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}
|
||||
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 member in ts_members:
|
||||
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, # No Response
|
||||
0:2, # No
|
||||
2:1, # Maybe
|
||||
1:0 # Yes
|
||||
|
||||
}.get(d['availability'].get('status_code')),
|
||||
d['member'].get('last_name'))
|
||||
)
|
||||
|
||||
|
||||
from teamsnap.forms import LineupEntryFormset, LineupEntryForm
|
||||
|
||||
formset = LineupEntryFormset(
|
||||
initial=[
|
||||
{
|
||||
"event_lineup_entry_id" : member['lineup_entry'].get('id'),
|
||||
"event_lineup_id" : member['lineup_entry'].get('event_lineup_id'),
|
||||
"event_id": event_id,
|
||||
"member_id" : member['member']['id'],
|
||||
"sequence" : member['lineup_entry'].get('sequence'),
|
||||
"label" : member['lineup_entry'].get('label'),
|
||||
}
|
||||
for member in members
|
||||
]
|
||||
)
|
||||
|
||||
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_lineup = [form for form in formset if form.initial.get('event_lineup_entry_id')]
|
||||
formset_lineup = sorted(
|
||||
formset_lineup,
|
||||
key=lambda d: d.initial.get('sequence',100)
|
||||
)
|
||||
formset_bench = [form for form in formset if
|
||||
form not in formset_lineup and
|
||||
form.availability.data['status_code'] in [2, 1]
|
||||
]
|
||||
formset_out = [form for form in formset if
|
||||
form not in formset_lineup and
|
||||
form not in formset_bench and
|
||||
not form.member.data['is_non_player']
|
||||
]
|
||||
|
||||
contexts.append({
|
||||
"event":ts_event,
|
||||
"formset": formset,
|
||||
"formset_bench":formset_bench,
|
||||
"formset_lineup":formset_lineup,
|
||||
"formset_out":formset_out
|
||||
})
|
||||
|
||||
return render(request, "teamsnap/lineup/multiple_edit.html", context={
|
||||
"team_id": team_id,
|
||||
"contexts":contexts
|
||||
})
|
||||
|
||||
def submit_lineup(request, team_id, event_id):
|
||||
from pyteamsnap.api import TeamSnap, EventLineupEntry, EventLineup
|
||||
from teamsnap.forms import LineupEntryFormset
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(0.5)
|
||||
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'))
|
||||
event_lineup_entry.data.update(data)
|
||||
# breakpoint()
|
||||
r.append(event_lineup_entry.put())
|
||||
# breakpoint()
|
||||
pass
|
||||
elif data.get('sequence') is not None and data.get('label'):
|
||||
event_lineup_entry = EventLineupEntry.new(client)
|
||||
event_lineup_entry.data.update(data)
|
||||
event_lineup_entry.data.update({"event_lineup_id":event_lineup_id})
|
||||
r.append(event_lineup_entry.post())
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
# breakpoint()
|
||||
pass
|
||||
# breakpoint()
|
||||
pass
|
||||
return HttpResponse(f'{team_id} {event_id}')
|
||||
pass
|
||||
|
||||
return HttpResponse(f'{team_id} {event_id}')
|
||||
|
||||
def image_generator(request, team_id, event_id):
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
|
||||
from pyteamsnap.api import TeamSnap, Event, Availability, Member, EventLineupEntry, EventLineup, AvailabilitySummary
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(0.5)
|
||||
|
||||
ts_event = Event.get(client, id=event_id)
|
||||
return render(request, "teamsnap/event/instagen.html", context = {"event":ts_event})
|
||||
|
||||
# @app.route('/get_matchup_image')
|
||||
def get_matchup_image(request, team_id, event_id, dimensions=None, background=None):
|
||||
from pyteamsnap.api import TeamSnap, EventLineupEntry, EventLineup, Event, Team, Opponent, Location
|
||||
from .utils.gen_image import Team as ImagegenTeam, Location as ImagegenLocation
|
||||
from .utils.gen_image import gen_image, gen_results_image
|
||||
import io
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
if request.GET:
|
||||
POSTPONED = request.GET.get('postponed', 'false') == 'true'
|
||||
INCLUDE_WINLOSS = request.GET.get('winloss', 'false') == 'true'
|
||||
BACKGROUND = request.GET.get('background', 'location')
|
||||
game_id = event_id
|
||||
dimensions = request.GET.get('dimensions')
|
||||
width = int(dimensions.split("x")[0])
|
||||
height = int(dimensions.split("x")[1])
|
||||
|
||||
teamsnap = TeamSnap(TOKEN)
|
||||
time.sleep(0.5)
|
||||
ts_event = Event.get(teamsnap, game_id).data
|
||||
fave_team = Team.get(teamsnap, ts_event['team_id']).data
|
||||
opponent_team = Opponent.get(teamsnap, ts_event['opponent_id']).data
|
||||
location = Location.get(teamsnap, ts_event['location_id']).data
|
||||
formatted_results = ts_event['formatted_results']
|
||||
if formatted_results:
|
||||
# L 4-3
|
||||
runs_for = formatted_results.split(" ")[1].split("-")[0]
|
||||
runs_against = formatted_results.split(" ")[1].split("-")[1]
|
||||
else:
|
||||
runs_for, runs_against = None, None
|
||||
|
||||
logo_image_directory = 'benchcoachproject/static/teamsnap/ig/logos-bw/{filename}.{ext}'
|
||||
venue_image_directory = 'benchcoachproject/static/teamsnap/ig/locations/{filename}.{ext}'
|
||||
|
||||
def shortname_from_name(name):
|
||||
return name.replace(" ", "").lower()
|
||||
|
||||
# date = parser.parse(ts_event['start_date'])
|
||||
# date = date.astimezone(ZoneInfo("America/Chicago"))
|
||||
game_info = {
|
||||
"date": ts_event['start_date'],
|
||||
"team_fave": ImagegenTeam(
|
||||
name=fave_team["name"],
|
||||
image_directory=logo_image_directory.format(filename=shortname_from_name(fave_team["name"]), ext="png")
|
||||
),
|
||||
"team_opponent": ImagegenTeam(
|
||||
name=opponent_team["name"],
|
||||
image_directory=logo_image_directory.format(filename=shortname_from_name(opponent_team["name"]),
|
||||
ext="png")
|
||||
),
|
||||
"location": ImagegenLocation(
|
||||
name=location['name'],
|
||||
image_directory=venue_image_directory.format(filename=shortname_from_name(location["name"]), ext="png"),
|
||||
# address=location['address']
|
||||
),
|
||||
"runs_for": runs_for,
|
||||
"runs_against": runs_against
|
||||
}
|
||||
|
||||
if not game_info['runs_for'] and not game_info['runs_against']:
|
||||
image = gen_image(**game_info, background=BACKGROUND, width=width, height=height)
|
||||
elif game_info['runs_for'] and game_info['runs_against']:
|
||||
image = gen_results_image(**game_info, background=BACKGROUND, width=width, height=height)
|
||||
else:
|
||||
raise Exception
|
||||
|
||||
imgByteArr = io.BytesIO()
|
||||
image.save(imgByteArr, format='PNG')
|
||||
imgByteArr = imgByteArr.getvalue()
|
||||
|
||||
return HttpResponse(imgByteArr, content_type="image/png")
|
||||
|
||||
def multi_lineup_choose(request, team_id):
|
||||
from teamsnap.forms import EventChooseForm
|
||||
from django.forms import formset_factory
|
||||
if not request.GET.get('num'):
|
||||
return HttpResponse(500)
|
||||
else:
|
||||
num = int(request.GET.get('num'))
|
||||
TEAM_ID = team_id
|
||||
TOKEN = request.user.profile.teamsnap_access_token
|
||||
no_past = bool(request.GET.get('no_past', 0))
|
||||
games_only = bool(request.GET.get('games_only', 0))
|
||||
from pyteamsnap.api import TeamSnap, Event, Location, Opponent
|
||||
client = TeamSnap(token=TOKEN)
|
||||
time.sleep(.5)
|
||||
ts_events = Event.search(client, team_id=TEAM_ID)
|
||||
if no_past:
|
||||
ts_events = [e for e in ts_events if e.data['start_date'] > datetime.datetime.now(datetime.timezone.utc)]
|
||||
if games_only:
|
||||
ts_events = [e for e in ts_events if e.data['is_game']]
|
||||
ts_events = {e.data['id']: e for e in ts_events}
|
||||
# ts_opponents = {o.data['id']:o for o in Opponent.search(client, team_id=TEAM_ID)}
|
||||
# ts_locations = {l.data['id']:l for l in Location.search(client, team_id=TEAM_ID)}
|
||||
# for event in ts_events:
|
||||
|
||||
EventChooseFormset = formset_factory(EventChooseForm, extra=num)
|
||||
formset = EventChooseFormset()
|
||||
|
||||
choices= [(id, e.data['formatted_title']) for id, e in ts_events.items()]
|
||||
|
||||
for form in formset:
|
||||
form.fields['event_id'].choices = choices
|
||||
|
||||
pass
|
||||
return render(request, "teamsnap/lineup/multiple_choose.html", context={"formset": formset, "team_id": team_id})
|
||||
Reference in New Issue
Block a user