Crude section/teams implementation
do not merge to main, very buggy rough implementation of sorting between teams and sections. I have rewritten many areas.
This commit is contained in:
parent
75a97d762b
commit
e2ad5676c7
@ -2,17 +2,17 @@
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Peg, Member, Team
|
||||
from .models import Member, Team, Section
|
||||
|
||||
|
||||
@admin.register(Peg)
|
||||
class PegAdmin(admin.ModelAdmin):
|
||||
"""Admin model for the Peg model."""
|
||||
# @admin.register(Peg)
|
||||
# class PegAdmin(admin.ModelAdmin):
|
||||
# """Admin model for the Peg model."""
|
||||
|
||||
change_list_template = "entities/bulk_pegging.html"
|
||||
readonly_fields = ("peg_number",)
|
||||
list_display = ("peg_number",)
|
||||
search_fields = ("peg_number",)
|
||||
# change_list_template = "entities/bulk_pegging.html"
|
||||
# readonly_fields = ("peg_number",)
|
||||
# list_display = ("peg_number",)
|
||||
# search_fields = ("peg_number",)
|
||||
|
||||
|
||||
@admin.register(Member)
|
||||
@ -28,14 +28,14 @@ class MemberAdmin(admin.ModelAdmin):
|
||||
class TeamAdmin(admin.ModelAdmin):
|
||||
"""Admin model for the Team model."""
|
||||
|
||||
readonly_fields = ("team_number",)
|
||||
list_display = ("team_number",)
|
||||
search_fields = ("team_number",)
|
||||
readonly_fields = ("name",)
|
||||
list_display = ("name",)
|
||||
search_fields = ("name",)
|
||||
|
||||
|
||||
# @admin.register(Section)
|
||||
# class SectionAdmin(admin.ModelAdmin):
|
||||
# """Admin model for the Section model."""
|
||||
@admin.register(Section)
|
||||
class SectionAdmin(admin.ModelAdmin):
|
||||
"""Admin model for the Section model."""
|
||||
|
||||
# list_display = ("character",)
|
||||
# search_fields = ("character",)
|
||||
list_display = ("name",)
|
||||
search_fields = ("name",)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,71 +2,71 @@
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"section_letter": "D"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 2,
|
||||
"fields": {
|
||||
"section_letter": "P"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 3,
|
||||
"fields": {
|
||||
"section_letter": "L"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 4,
|
||||
"fields": {
|
||||
"section_letter": "M"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 2,
|
||||
"fields": {
|
||||
"section_letter": "K"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 3,
|
||||
"fields": {
|
||||
"section_letter": "Q"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 4,
|
||||
"fields": {
|
||||
"section_letter": "V"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 5,
|
||||
"fields": {
|
||||
"section_letter": "Z"
|
||||
"section_letter": "U"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 6,
|
||||
"fields": {
|
||||
"section_letter": "Y"
|
||||
"section_letter": "H"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 7,
|
||||
"fields": {
|
||||
"section_letter": "J"
|
||||
"section_letter": "A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 8,
|
||||
"fields": {
|
||||
"section_letter": "W"
|
||||
"section_letter": "D"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 9,
|
||||
"fields": {
|
||||
"section_letter": "T"
|
||||
"section_letter": "P"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "mainapp.team",
|
||||
"pk": 10,
|
||||
"fields": {
|
||||
"section_letter": "F"
|
||||
"section_letter": "G"
|
||||
}
|
||||
}
|
||||
]
|
@ -1,12 +1,46 @@
|
||||
import random
|
||||
import names
|
||||
import json
|
||||
from typing import Optional, List, Set
|
||||
from string import ascii_uppercase
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from mainapp.models import Member, Team
|
||||
|
||||
from mainapp.models import Member, Team, SectionValidator
|
||||
|
||||
|
||||
# TODO: refactor this file like create_teams_fixtures.py
|
||||
|
||||
|
||||
# SECTION_LETTERS = ascii_uppercase
|
||||
|
||||
|
||||
# def get_next_available_section(member: Member, section_validator: SectionValidator) -> Optional[str]:
|
||||
# """Returns the next available section for a member."""
|
||||
# member_sections = member.sections.all().values_list('name', flat=True)
|
||||
# used_sections = set(member_sections)
|
||||
|
||||
# if not member_sections:
|
||||
# return "A"
|
||||
|
||||
# used_sections = sorted(used_sections)
|
||||
|
||||
# last_section = member_sections[-1]
|
||||
# last_section_index = SECTION_LETTERS.index(last_section)
|
||||
|
||||
# for i in range(last_section_index + 1, len(SECTION_LETTERS)):
|
||||
# section = SECTION_LETTERS[i]
|
||||
# if section_validator.is_valid_section(section) and section not in used_sections:
|
||||
# return section
|
||||
|
||||
# for i in range(last_section_index - 1, -1, -1):
|
||||
# section = SECTION_LETTERS[i]
|
||||
# if section_validator.is_valid_section(section) and section not in used_sections:
|
||||
# return section
|
||||
|
||||
# return None
|
||||
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Creates a fixture with randomly generated Member objects"
|
||||
|
||||
@ -25,11 +59,9 @@ class Command(BaseCommand):
|
||||
for _ in range(num_members):
|
||||
first_name = names.get_first_name()
|
||||
last_name = names.get_last_name()
|
||||
member = Member(first_name=first_name, last_name=last_name, team=team)
|
||||
member = Member.objects.create(first_name=first_name, last_name=last_name, team=team)
|
||||
members.append(member)
|
||||
|
||||
Member.objects.bulk_create(members)
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f"Created {num_members} members."))
|
||||
|
||||
# create a members fixture file
|
||||
@ -42,7 +74,7 @@ class Command(BaseCommand):
|
||||
"first_name": member.first_name,
|
||||
"last_name": member.last_name,
|
||||
"team": member.team_id,
|
||||
"peg_number": member.peg_number
|
||||
"peg_number": member.peg_number,
|
||||
}
|
||||
}
|
||||
members_fixture.append(member_fixture)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 4.1.5 on 2023-05-07 21:57
|
||||
# Generated by Django 4.1.5 on 2023-05-09 22:52
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
@ -14,16 +14,16 @@ class Migration(migrations.Migration):
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Peg',
|
||||
name='Section',
|
||||
fields=[
|
||||
('peg_number', mainapp.models.ReusableAutoField(default=mainapp.models.ReusableAutoField.get_default, editable=False, primary_key=True, serialize=False)),
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(editable=False, max_length=3, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Team',
|
||||
fields=[
|
||||
('team_number', mainapp.models.ReusableAutoField(default=mainapp.models.ReusableAutoField.get_default, editable=False, primary_key=True, serialize=False)),
|
||||
('section_letter', models.CharField(choices=[('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D'), ('E', 'E'), ('F', 'F'), ('G', 'G'), ('H', 'H'), ('I', 'I'), ('J', 'J'), ('K', 'K'), ('L', 'L'), ('M', 'M'), ('N', 'N'), ('O', 'O'), ('P', 'P'), ('Q', 'Q'), ('R', 'R'), ('S', 'S'), ('T', 'T'), ('U', 'U'), ('V', 'V'), ('W', 'W'), ('X', 'X'), ('Y', 'Y'), ('Z', 'Z')], max_length=1, unique=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -33,6 +33,7 @@ class Migration(migrations.Migration):
|
||||
('first_name', models.CharField(max_length=255)),
|
||||
('last_name', models.CharField(max_length=255)),
|
||||
('peg_number', models.PositiveIntegerField(null=True, unique=True)),
|
||||
('section', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='mainapp.section')),
|
||||
('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='members', to='mainapp.team', validators=[mainapp.models.validate_team_size])),
|
||||
],
|
||||
),
|
||||
|
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.1.5 on 2023-05-09 23:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mainapp', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='team',
|
||||
old_name='team_number',
|
||||
new_name='name',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='section',
|
||||
name='name',
|
||||
field=models.CharField(max_length=3, unique=True),
|
||||
),
|
||||
]
|
@ -31,13 +31,101 @@ class ReusableAutoField(models.PositiveIntegerField):
|
||||
return self.get_next_available_id(self.model)
|
||||
|
||||
|
||||
class Peg(models.Model):
|
||||
"""Represents a person's peg"""
|
||||
# class Peg(models.Model):
|
||||
# """Represents a person's peg"""
|
||||
|
||||
peg_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
||||
# peg_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
||||
|
||||
def __str__(self):
|
||||
return f"Peg {self.peg_number}"
|
||||
# def __str__(self):
|
||||
# return f"Peg {self.peg_number}"
|
||||
|
||||
|
||||
class SectionValidator:
|
||||
"""Validation class for the `section` field on the `member` model."""
|
||||
|
||||
def __init__(self, max_value="ZZZ"):
|
||||
self.max_value = max_value.upper()
|
||||
self.alphabet_size = ord("Z") - ord("A") + 1
|
||||
|
||||
def is_valid(self, section: str, team_sections: list[str]=None) -> bool:
|
||||
"""Returns boolean if the section passed is valid."""
|
||||
section = section.upper()
|
||||
|
||||
if not self._is_alphanumeric(section):
|
||||
return False
|
||||
|
||||
if not self._is_in_alphabet(section[0]):
|
||||
return False
|
||||
|
||||
if not self._is_in_range(section):
|
||||
return False
|
||||
|
||||
if team_sections:
|
||||
if not self._is_unique(section, team_sections):
|
||||
return False
|
||||
|
||||
if not self._is_not_adjacent(section, team_sections):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _is_alphanumeric(self, section: str) -> bool:
|
||||
"""Returns boolean if all characters in the passed string are alphanumerical."""
|
||||
return all(c.isalnum() for c in section)
|
||||
|
||||
def _is_in_alphabet(self, c) -> bool:
|
||||
"""Returns boolean if the passed character is alphabetical."""
|
||||
return "A" <= c <= "Z"
|
||||
|
||||
def _is_in_range(self, section) -> bool:
|
||||
"""Returns boolean if the passed section less or equal to the max value."""
|
||||
section_value = self._section_value(section)
|
||||
max_value = self._section_value(self.max_value)
|
||||
|
||||
return section_value <= max_value
|
||||
|
||||
def _is_unique(self, section, team_sections) -> bool:
|
||||
"""Returns boolean if the passed section is unique amongst `team_sections`."""
|
||||
return section not in team_sections
|
||||
|
||||
def _is_not_adjacent(self, section, team_sections) -> bool:
|
||||
"""Returns boolean if the passed section is not adjacent to any `team_sections`."""
|
||||
for team_section in team_sections:
|
||||
team_section_value = self._section_value(team_section)
|
||||
section_value = self._section_value(section)
|
||||
if abs(team_section_value - section_value) <= 1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _section_value(self, section):
|
||||
"""Returns the value of the passed section."""
|
||||
n = len(section)
|
||||
value = sum((ord(c) - ord("A") + 1) * self.alphabet_size ** (n - i - 1) for i, c in enumerate(section))
|
||||
return value
|
||||
|
||||
|
||||
class Section(models.Model):
|
||||
"""Represents a fishing area. Members can be assigned to a section,
|
||||
but no 2 teammates can be in the same or adjacent section."""
|
||||
|
||||
name = models.CharField(max_length=3, unique=True, null=False)
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
validator = SectionValidator(max_value="ZZZ")
|
||||
if not validator.is_valid(self.name):
|
||||
raise ValidationError("Invalid section value.")
|
||||
|
||||
self.name = self.name.upper()
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def members(self):
|
||||
return Member.objects.filter(section=self)
|
||||
|
||||
|
||||
def validate_team_size(value):
|
||||
@ -52,7 +140,7 @@ class Member(models.Model):
|
||||
last_name = models.CharField(max_length=255)
|
||||
team = models.ForeignKey("Team", on_delete=models.SET_NULL, null=True, blank=True, validators=(validate_team_size,), related_name='members')
|
||||
peg_number = models.PositiveIntegerField(null=True, editable=True, unique=True)
|
||||
# peg = models.OneToOneField("Peg", on_delete=models.SET_NULL, null=True, blank=True)
|
||||
section = models.ForeignKey(to=Section, on_delete=models.SET_NULL, null=True, swappable=True)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
@ -65,6 +153,13 @@ class Member(models.Model):
|
||||
if peg_numbers:
|
||||
self.peg_number = min (peg_numbers)
|
||||
|
||||
# def clean(self):
|
||||
# super().clean()
|
||||
|
||||
# validator = SectionValidator(max_value="ZZZ")
|
||||
# if not validator.is_valid(self.section):
|
||||
# raise ValidationError("Invalid section value.")
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.first_name} {self.last_name} (team {self.team.team_number}))"
|
||||
|
||||
@ -79,53 +174,25 @@ BLOCKED_SECTION_LETTERS = ["i"] # lowercase only, sections cannot be any of the
|
||||
class Team(models.Model):
|
||||
"""Represents a team"""
|
||||
|
||||
team_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
||||
section_letter = models.CharField(max_length=1, unique=True, choices=[
|
||||
(char, char) for char in ascii_uppercase if char.lower() not in BLOCKED_SECTION_LETTERS
|
||||
])
|
||||
name = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
||||
# section_letter = models.CharField(max_length=1, unique=True, choices=[
|
||||
# (char, char) for char in ascii_uppercase if char.lower() not in BLOCKED_SECTION_LETTERS
|
||||
# ])
|
||||
|
||||
def __str__(self):
|
||||
return f"Team {self.team_number}"
|
||||
return f"Team {self.name}"
|
||||
|
||||
@property
|
||||
def members(self) -> list[Member]:
|
||||
Member.objects.filter(team=self)
|
||||
return Member.objects.filter(team=self)
|
||||
|
||||
|
||||
def validate_section_character(value):
|
||||
"""Validates the section character"""
|
||||
# def validate_section_character(value):
|
||||
# """Validates the section character"""
|
||||
|
||||
value = value.upper()
|
||||
banned_characters = ["I"]
|
||||
# value = value.upper()
|
||||
# banned_characters = ["I"]
|
||||
|
||||
if value in banned_characters:
|
||||
raise ValidationError(f"The character <{value}> is a prohibited character.")
|
||||
# if value in banned_characters:
|
||||
# raise ValidationError(f"The character <{value}> is a prohibited character.")
|
||||
|
||||
|
||||
# class Section(models.Model):
|
||||
# """Represents a section of the scoreboard"""
|
||||
|
||||
# # character field stores a single character but doesnt allow for 'I' or 'i'
|
||||
# character = models.CharField(primary_key=True, max_length=1, validators=(validate_section_character, ))
|
||||
|
||||
# def clean(self):
|
||||
# self.character = self.character.upper()
|
||||
|
||||
# def __str__(self):
|
||||
# return f"Section {self.character}"
|
||||
|
||||
|
||||
#class Scoreboard(models.Model):
|
||||
# class Status(models.IntegerChoices):
|
||||
# ACTIVE = 1, "Active"
|
||||
# INACTIVE = 2, "Inactive"
|
||||
# ARCHIVED = 3, "Archived"
|
||||
#
|
||||
# name = models.CharField(max_length=255)
|
||||
# category = models.CharField(max_length=255)
|
||||
# price = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
# cost = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
# status = models.PositiveSmallIntegerField(choices=Status.choices)
|
||||
#
|
||||
# def __str__(self):
|
||||
# return self.name
|
@ -37,11 +37,11 @@
|
||||
<h3 class="h6 mb-3">Sort groups by</h3>
|
||||
<div>
|
||||
<div class="d-inline-block form-check">
|
||||
<input type="radio" class="form-check-input" checked value="team_number" name="sortTeams" id="sortTeamsName">
|
||||
<input type="radio" class="form-check-input" checked value="team" name="sortGroups" id="sortTeamsName">
|
||||
<label for="sortTeamsName" class="form-check-label">Teams</label>
|
||||
</div>
|
||||
<div class="d-inline-block form-check ms-4">
|
||||
<input type="radio" class="form-check-input" value="section_letter" name="sortTeams" id="sortTeamsSection">
|
||||
<input type="radio" class="form-check-input" value="section" name="sortGroups" id="sortTeamsSection">
|
||||
<label for="sortTeamsSection" class="form-check-label">Sections</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@ urlpatterns = [
|
||||
path('scoreboard/', views.scoreboard, name='scoreboard'),
|
||||
path('teams/', views.teams, name='teams'),
|
||||
|
||||
path('bulk-peg/', views.bulk_create_pegs, name='bulk-peg'),
|
||||
# path('bulk-peg/', views.bulk_create_pegs, name='bulk-peg'),
|
||||
path('get-teams/', views.get_teams, name='get-teams'),
|
||||
path('update-member/', views.update_member, name='update-member')
|
||||
]
|
@ -6,7 +6,7 @@ from django.shortcuts import render, redirect
|
||||
from django.http import JsonResponse
|
||||
from django.db.models import Q, Case, When, Value, IntegerField
|
||||
|
||||
from .models import Peg, Team, Member
|
||||
from .models import Team, Member, Section
|
||||
|
||||
|
||||
def index(request):
|
||||
@ -21,15 +21,15 @@ def scoreboard(request):
|
||||
def teams(request):
|
||||
return render(request, 'teams.html')
|
||||
|
||||
def bulk_create_pegs(request):
|
||||
"""Bulk create pegs"""
|
||||
# def bulk_create_pegs(request):
|
||||
# """Bulk create pegs"""
|
||||
|
||||
number_of_pegs = request.POST.get("pegAmount")
|
||||
for i in range(int(number_of_pegs)):
|
||||
Peg.objects.create()
|
||||
# number_of_pegs = request.POST.get("pegAmount")
|
||||
# for i in range(int(number_of_pegs)):
|
||||
# Peg.objects.create()
|
||||
|
||||
# return to previous page
|
||||
return redirect(request.META.get('HTTP_REFERER'))
|
||||
# # return to previous page
|
||||
# return redirect(request.META.get('HTTP_REFERER'))
|
||||
|
||||
def get_teams(request):
|
||||
"""Returns a JsonResponse containing a dictionary with a k/v pair for a list of teams.
|
||||
@ -44,10 +44,11 @@ def get_teams(request):
|
||||
return
|
||||
|
||||
search = request.POST.get("search")
|
||||
sort_teams = request.POST.get("sortTeams") or "team_number"
|
||||
sort_groups = request.POST.get("sortGroups") or "team"
|
||||
sort_members = request.POST.get("sortMembers") or "peg_number"
|
||||
|
||||
teams = Team.objects.order_by(sort_teams).all()
|
||||
group_object = Team if sort_groups == "team" else Section
|
||||
groups = group_object.objects.order_by("name").all()
|
||||
|
||||
# Filter out teams that don't contain members being searched for
|
||||
if search:
|
||||
@ -61,31 +62,32 @@ def get_teams(request):
|
||||
]
|
||||
)
|
||||
)
|
||||
teams = teams.filter(members__in=members).distinct()
|
||||
groups = groups.filter(members__in=members).distinct()
|
||||
|
||||
# Create a dictionary for the data that is JSON safe
|
||||
response_data = {"teams": []}
|
||||
for team in teams:
|
||||
team_data = {
|
||||
"team_number": team.team_number,
|
||||
"section_letter": team.section_letter if team.section_letter else None,
|
||||
response_data = {"groups": []}
|
||||
for group in groups:
|
||||
group_data = {
|
||||
"name": group.name,
|
||||
"members": [
|
||||
{
|
||||
"first": member.first_name,
|
||||
"last": member.last_name,
|
||||
"id": member.id,
|
||||
"team": team.team_number,
|
||||
"peg": member.peg_number,
|
||||
"section": team.section_letter if team.section_letter else None
|
||||
"team": member.team.name if member.team else None,
|
||||
"section": member.section.name if member.section else None
|
||||
}
|
||||
for member in team.members.order_by(sort_members).all()
|
||||
for member in group.members.order_by(sort_members).all()
|
||||
]
|
||||
}
|
||||
response_data["teams"].append(team_data)
|
||||
response_data["groups"].append(group_data)
|
||||
|
||||
response_data["sortTeams"] = sort_teams
|
||||
response_data["sortGroups"] = sort_groups
|
||||
response_data["sortMembers"] = sort_members
|
||||
|
||||
print(sort_groups, sort_members)
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
def update_member(request):
|
||||
|
@ -34,9 +34,9 @@ $(document).ready(() => {
|
||||
});
|
||||
|
||||
// Load the last saved sort settings TODO: use local storage so it only saves on one reload
|
||||
const sortTeamsValue = localStorage.getItem("sortTeams");
|
||||
const sortTeamsValue = localStorage.getItem("sortGroups");
|
||||
if (sortTeamsValue !== null) {
|
||||
$("#sortForm input[name='sortTeams']").val([sortTeamsValue]);
|
||||
$("#sortForm input[name='sortGroups']").val([sortTeamsValue]);
|
||||
}
|
||||
|
||||
const sortMembersValue = localStorage.getItem("sortMembers");
|
||||
@ -70,30 +70,31 @@ $(document).ready(() => {
|
||||
function getFilters() {
|
||||
return [
|
||||
$("#search").val(),
|
||||
$("input[name='sortTeams']:checked", "#sortForm").val(),
|
||||
$("input[name='sortGroups']:checked", "#sortForm").val(),
|
||||
$("input[name='sortMembers']:checked", "#sortForm").val()
|
||||
]
|
||||
}
|
||||
|
||||
function loadTeams(teams, highlightText="") {
|
||||
function loadTeams(groups, highlightText="", groupType) {
|
||||
$("#teamsContainer").html(""); // Clear the previous listed teams
|
||||
|
||||
if (teams.length < 1) {
|
||||
if (groups.length < 1) {
|
||||
$("#teamsNotFound").show();
|
||||
}
|
||||
|
||||
groupType = groupType.toUpperCase();
|
||||
|
||||
// Iterate over and add each team
|
||||
teams.forEach((team) => {
|
||||
groups.forEach((group) => {
|
||||
$("#teamsContainer").append(
|
||||
`<div class='col-12 col-md-6 col-xl-4 mb-4'>
|
||||
<div
|
||||
class='team px-4 py-3 bg-body-tertiary bg-gradient rounded h-100 fluid-hover-zoom shadow-sm md-shadow-on-hover'
|
||||
data-number='${team.team_number}'
|
||||
data-section='${team.section_letter}'>
|
||||
data-number='${group.name}'>
|
||||
<h3>
|
||||
<span class='fs-4'>
|
||||
<span class='fs-6'>TEAM</span>
|
||||
${team.team_number}
|
||||
<span class='fs-6'>${groupType}</span>
|
||||
${group.name}
|
||||
</span>
|
||||
<button class='btn btn-sm btn-light float-end border-0 me-1'>
|
||||
<i class='bi bi-gear fs-6'></i>
|
||||
@ -106,8 +107,10 @@ function loadTeams(teams, highlightText="") {
|
||||
);
|
||||
|
||||
// While we have the team, iterate over and add it's members
|
||||
team.members.forEach((member) => {
|
||||
group.members.forEach((member) => {
|
||||
const fullname = member.first + " " + member.last;
|
||||
const oppositeGroupType = groupType === "SECTION"? "Team" : "Section";
|
||||
const oppositeGroupName = groupType === "SECTION"? member.team : member.section;
|
||||
|
||||
$("#teamsContainer").find(".team-members").last().append(
|
||||
`<li class='mb-3 rounded w-100 fluid-hover-zoom'>
|
||||
@ -117,13 +120,14 @@ function loadTeams(teams, highlightText="") {
|
||||
data-last='${member.last}'
|
||||
data-member-id='${member.id}'
|
||||
data-team-number='${member.team}'
|
||||
data-peg-number='${member.peg}'>
|
||||
data-peg-number='${member.peg}'
|
||||
data-section='${member.section}'>
|
||||
<div class='px-3 py-2 w-100'>
|
||||
<div class='badge bg-secondary-subtle text-body fixed-badge' data-bs-title='Peg ${member.peg}' data-bs-toggle='tooltip'>
|
||||
${member.peg}
|
||||
</div>
|
||||
<div class='badge bg-secondary-subtle text-body fixed-badge' data-bs-title='Section ${member.section}' data-bs-toggle='tooltip'>
|
||||
${member.section}
|
||||
<div class='badge bg-secondary-subtle text-body fixed-badge' data-bs-title='${oppositeGroupType} ${oppositeGroupName}' data-bs-toggle='tooltip'>
|
||||
${oppositeGroupName}
|
||||
</div>
|
||||
<div class='d-inline-block ms-2 team-member-fullname'>
|
||||
${fullname}
|
||||
@ -176,20 +180,20 @@ function loadTeams(teams, highlightText="") {
|
||||
});
|
||||
}
|
||||
|
||||
function fetchAndLoadTeams(search="", sortTeams="", sortMembers="") {
|
||||
function fetchAndLoadTeams(search="", sortGroups="", sortMembers="") {
|
||||
$.ajax({
|
||||
url: getTeamsUrl,
|
||||
type: "post",
|
||||
data: {
|
||||
"csrfmiddlewaretoken": csrfMiddlewareToken,
|
||||
"search": search,
|
||||
"sortTeams": sortTeams,
|
||||
"sortGroups": sortGroups,
|
||||
"sortMembers": sortMembers
|
||||
},
|
||||
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
|
||||
success: (result) => {
|
||||
teamsLoading(false);
|
||||
loadTeams(result.teams, search);
|
||||
loadTeams(result.groups, search, result.sortGroups);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -298,7 +302,7 @@ function saveEditMemberModal(memberId) {
|
||||
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
|
||||
success: (result) => {
|
||||
teamsLoading(false);
|
||||
loadTeams(result.teams, search);
|
||||
loadTeams(result.teams, search, result.sortGroups);
|
||||
$("#editMemberModal").modal("hide");
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user