Fix the referee PDF's card background, make locations searchable, and add game end times to the API
Referee PDF: the info-card background used CSS color-mix(), which WeasyPrint doesn't support -- the rule was silently dropped, leaving the card with no background at all. Computed in Python instead (management/pdf.py) and baked into the template as a plain hex value; the tint is based on the club's primary_color, falling back to secondary_color when primary is itself (near) black or white, where a straight tint would be invisible or too harsh. Event forms: the location picker now shows "Name — City" (plus the country when it isn't Belgium) and is searchable by name or city, reusing the existing single-select searchable-select.js widget. Games API: GameOut now carries `end` (explicit, or start + 2h when a GAME was saved without one -- Event.save() sets this, never overwriting an explicit end; other event kinds are untouched). /games/upcoming/ now includes anything not yet finished rather than only things that haven't started, so a game already in progress keeps showing up until its window closes; `status` was adjusted to match so a game returned there never calls itself "finished". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -226,6 +226,17 @@ class SponsorForm(forms.ModelForm):
|
||||
return cleaned
|
||||
|
||||
|
||||
def _location_label(location) -> str:
|
||||
""""Name — City" for the location picker, plus the country when it isn't
|
||||
Belgium (the club's home country and, in practice, nearly every location
|
||||
a club will ever add) -- lets an admin tell two same-named venues apart,
|
||||
or spot an away trip abroad, straight from the dropdown."""
|
||||
label = f"{location.name} — {location.city}"
|
||||
if location.country.code != "BE":
|
||||
label += f", {location.country.name}"
|
||||
return label
|
||||
|
||||
|
||||
class EventAudienceFormMixin:
|
||||
"""Shared club/user-scoped audience fields for EventForm and EventSeriesForm:
|
||||
teams restricted to the ones the requester manages (all of them for an
|
||||
@@ -238,6 +249,7 @@ class EventAudienceFormMixin:
|
||||
self.user = user
|
||||
self.fields["teams"].queryset = Team.objects.filter(club=club) if is_club_admin(user, club) else teams_managed_by(user, club)
|
||||
self.fields["location"].queryset = Location.objects.filter(club=club)
|
||||
self.fields["location"].label_from_instance = _location_label
|
||||
self.fields["opponent"].queryset = Opponent.objects.filter(club=club)
|
||||
members = Member.objects.filter(member_of__club=club).distinct()
|
||||
self.fields["invited_members"].queryset = members
|
||||
@@ -253,6 +265,7 @@ _AUDIENCE_WIDGETS = {
|
||||
"teams": forms.SelectMultiple(attrs={"data-searchable": "true", "data-search-placeholder": _("Type a team to search...")}),
|
||||
"invited_members": forms.SelectMultiple(attrs={"data-searchable": "true", "data-search-placeholder": _("Type a name to search...")}),
|
||||
"excluded_members": forms.SelectMultiple(attrs={"data-searchable": "true", "data-search-placeholder": _("Type a name to search...")}),
|
||||
"location": forms.Select(attrs={"data-searchable": "true", "data-search-placeholder": _("Type a name or city to search...")}),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user