Adding Teams & Sections is functional-ish
This commit is contained in:
parent
8dfe4eb9f2
commit
628764a338
@ -1,5 +1,7 @@
|
||||
"""Models for the mainapp."""
|
||||
|
||||
from string import ascii_uppercase
|
||||
|
||||
from django.db import models
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
@ -96,12 +98,65 @@ class SectionValidator:
|
||||
return value
|
||||
|
||||
|
||||
|
||||
class SectionManager(models.Manager):
|
||||
|
||||
@staticmethod
|
||||
def get_max_section():
|
||||
max_section = None
|
||||
max_number = -1
|
||||
|
||||
# Iterate through all sections in the database
|
||||
for section in Section.objects.all():
|
||||
section_name = section.name
|
||||
section_number = 0
|
||||
|
||||
# Calculate the section number based on the section name
|
||||
for i, char in enumerate(section_name):
|
||||
section_number += (ord(char) - ord('A') + 1) * (26 ** (len(section_name) - i - 1))
|
||||
|
||||
# Check if this section has a higher number than the current maximum
|
||||
if section_number > max_number:
|
||||
max_number = section_number
|
||||
max_section = section_name
|
||||
|
||||
return max_section
|
||||
|
||||
@staticmethod
|
||||
def find_next_section(current_section):
|
||||
if not current_section:
|
||||
return 'A'
|
||||
|
||||
# Split current section name into a list of characters
|
||||
chars = list(current_section)
|
||||
|
||||
# Increment the last character
|
||||
chars[-1] = chr(ord(chars[-1]) + 1)
|
||||
|
||||
# Check if the last character is "Z", and carry over to the next character if necessary
|
||||
for i in range(len(chars) - 1, -1, -1):
|
||||
if chars[i] > 'Z':
|
||||
chars[i] = 'A'
|
||||
if i == 0:
|
||||
# If the first character needs to be incremented, add a new character "A"
|
||||
chars.insert(0, 'A')
|
||||
else:
|
||||
# Increment the previous character
|
||||
chars[i - 1] = chr(ord(chars[i - 1]) + 1)
|
||||
else:
|
||||
break
|
||||
|
||||
# Join the characters back into a string and return the result
|
||||
return ''.join(chars)
|
||||
|
||||
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)
|
||||
|
||||
objects = SectionManager()
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
@ -118,52 +173,6 @@ class Section(models.Model):
|
||||
def get_members(self):
|
||||
return Member.objects.filter(section=self)
|
||||
|
||||
@property
|
||||
def section_after(self):
|
||||
"""Returns the next section after this one, or none if not found."""
|
||||
sections = [sec for sec in Section.objects.all()]
|
||||
sections.sort(key=lambda sec: sec.name)
|
||||
try:
|
||||
return sections[sections.index(self) + 1]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@property
|
||||
def section_before(self):
|
||||
"""Returns the last section before this one, or none if not found."""
|
||||
sections = [sec for sec in Section.objects.all()]
|
||||
sections.sort(key=lambda sec: sec.name)
|
||||
try:
|
||||
return sections[sections.index(self) - 1]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def is_joinable(self, member, /) -> bool:
|
||||
"""Returns boolean if a member is able to join this section."""
|
||||
|
||||
if not member.team:
|
||||
return True
|
||||
|
||||
teammates = [teammate for teammate in Member.objects.filter(team=member.team)]
|
||||
|
||||
section_after = self.section_after.get_members if self.section_after else []
|
||||
section_before = self.section_before.get_members if self.section_before else []
|
||||
|
||||
for teammate in teammates:
|
||||
if teammate in section_after:
|
||||
return False
|
||||
|
||||
if teammate in section_before:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
return any(
|
||||
teammate in section_after or teammate in section_before
|
||||
for teammate in teammates
|
||||
)
|
||||
|
||||
|
||||
|
||||
class Member(models.Model):
|
||||
"""Represents a member of a team"""
|
||||
@ -192,11 +201,18 @@ class Member(models.Model):
|
||||
def fullname(self) -> str:
|
||||
return f"{self.first_name} {self.last_name}"
|
||||
|
||||
|
||||
class TeamManager(models.Manager):
|
||||
pass
|
||||
|
||||
|
||||
class Team(models.Model):
|
||||
"""Represents a team"""
|
||||
|
||||
name = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
||||
|
||||
objects = TeamManager()
|
||||
|
||||
def __str__(self):
|
||||
return f"Team {self.name}"
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
</div> -->
|
||||
<div class="fluid-hover-zoom d-flex flex-wrap justify-content-center shadow-sm md-shadow on-hover bg-body-tertiary rounded text-center p-5 h-100">
|
||||
<h3 class="h2 w-100">
|
||||
Member Management
|
||||
Angler Management
|
||||
<div class="border-company border-bottom border-2 w-100 pt-1"></div>
|
||||
</h3>
|
||||
<p class="mt-3">
|
||||
|
@ -1,7 +1,8 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}
|
||||
Member Management |
|
||||
Manage Anglers |
|
||||
{% endblock title %}
|
||||
|
||||
{% block style %}
|
||||
@ -10,21 +11,22 @@
|
||||
{% endblock style %}
|
||||
|
||||
{% block content %}
|
||||
<div class="bg-body p-4">
|
||||
<div class="bg-body p-4 d-flex">
|
||||
<a href="{% url 'index' %}" class="btn btn-company px-4">Back</a>
|
||||
<img class="ms-auto" width="40" src="{% static 'img/logo.webp' %}">
|
||||
</div>
|
||||
|
||||
<div class="container my-4 p-4 pb-0 bg-body rounded">
|
||||
<div class="row mb-4">
|
||||
<div class="col-12 col-xl-4 d-flex">
|
||||
<h3 class="mb-3 mb-xl-0">
|
||||
Member Management
|
||||
Manage Anglers
|
||||
<div class="border-company border-bottom border-2 w-100 pt-1"></div>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-sm-3 col-md-6 col-xl-4 mb-3 mb-sm-0">
|
||||
<div class="input-group justify-content-xl-end">
|
||||
<button class="btn border-secondary-subtle btn-outline-company" id="addMember" data-bs-toggle="tooltip" data-bs-title="Add Member">
|
||||
<button class="btn border-secondary-subtle btn-outline-company" id="addMember" data-bs-toggle="tooltip" data-bs-title="Add Angler">
|
||||
<i class="bi bi-person"></i>
|
||||
</button>
|
||||
<button class="btn border-secondary-subtle btn-outline-company" id="addTeam" data-bs-toggle="tooltip" data-bs-title="Add Team">
|
||||
@ -40,7 +42,7 @@
|
||||
<button type="button" data-bs-toggle="dropdown" class="btn btn-outline-company border-secondary-subtle">
|
||||
<i class="bi bi-sort-up"></i>
|
||||
</button>
|
||||
<input type="search" class="form-control border-secondary-subtle shadow-none" placeholder="Search Members" id="search">
|
||||
<input type="search" class="form-control border-secondary-subtle shadow-none" placeholder="Search Anglers" id="search">
|
||||
<button type="button" class="btn btn-outline-company border-secondary-subtle rounded-end" id="searchButton"><i class="bi bi-search"></i></button>
|
||||
<form id="sortForm">
|
||||
<ul class="dropdown-menu py-3 text-body-secondary bg-body-tertiary border border-light-subtle shadow-sm justify-self-center mt-2" onclick="event.stopPropagation()">
|
||||
@ -59,7 +61,7 @@
|
||||
</li>
|
||||
<li class="dropdown-divider my-3 mx-4 bg-light-subtle"></li>
|
||||
<li class="px-4">
|
||||
<h3 class="h6 mb-3">Sort members by</h3>
|
||||
<h3 class="h6 mb-3">Sort anglers by</h3>
|
||||
<div>
|
||||
<div class="d-inline-block form-check">
|
||||
<input type="radio" class="form-check-input" value="first_name" name="sortMembers" id="sortMembersName">
|
||||
@ -91,6 +93,38 @@
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Edit Section Modal -->
|
||||
<div class="modal fade" id="editSectionModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content border-0">
|
||||
<div class="modal-header border-0">
|
||||
<h3 class="modal-title fs-5" id="editTeamTitle">
|
||||
Section Character Here
|
||||
<div class="border-company border-bottom border-2 w-100 pt-1"></div>
|
||||
</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="col-md-6 d-flex">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text" data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="Section Character">
|
||||
<i class="bi bi-layers"></i>
|
||||
</span>
|
||||
<input type="text" name="editSectionName" id="editSectionName" class="form-control" minlength="1" maxlength="3" value="A">
|
||||
</div>
|
||||
<button type="button" id="editSectionNameButton" class="btn btn-outline-company border-secondary-subtle ms-3" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-title="Find next available character">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-6 mt-2 text-danger" id="editSectionNameError" style="display: hidden"></div>
|
||||
</div>
|
||||
<div class="modal-footer border-0">
|
||||
<button type="button" class="btn btn-company px-4" id="saveEditSectionModal">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Team Modal -->
|
||||
<div class="modal fade" id="editTeamModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
@ -103,32 +137,21 @@
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-6 d-flex">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<span class="input-group-text" data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="Team number">
|
||||
<i class="bi bi-tag"></i>
|
||||
</span>
|
||||
<div class="form-floating">
|
||||
<input type="number" class="form-control" name="editTeamName" id="editTeamName">
|
||||
<label for="editTeamName">Number</label>
|
||||
</div>
|
||||
<input type="number" name="editTeamNumber" id="editTeamNumber" class="form-control" min="1" max="9999" value="1">
|
||||
</div>
|
||||
<button type="button" id="editTeamNumberButton" class="btn btn-outline-company border-secondary-subtle ms-3" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-title="Find next available number">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- <form id="editTeamForm">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<label for="editTeamNumber" class="form-label">Team Number</label>
|
||||
<input type="number" name="editTeamNumber" class="form-control" id="editTeamNumber">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="editTeamSection" class="form-label">Section Letter</label>
|
||||
<input type="text" name="editTeamSection" class="form-control" id="editTeamSection">
|
||||
</div>
|
||||
</div>
|
||||
</form> -->
|
||||
<div class="col-md-6 mt-2 text-danger" id="editTeamNumberError" style="display: hidden"></div>
|
||||
</div>
|
||||
<div class="modal-footer border-0">
|
||||
<button type="button" class="btn btn-company" id="saveEditTeamModal">Save Changes</button>
|
||||
<button type="button" class="btn btn-company px-4" id="saveEditTeamModal">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -140,7 +163,7 @@
|
||||
<div class="modal-content border-0">
|
||||
<div class="modal-header border-0">
|
||||
<h3 class="modal-title fs-5 color" id="editMemberName">
|
||||
Member Name Here
|
||||
Angler Name Here
|
||||
<div class="border-company border-bottom border-2 w-100 pt-1"></div>
|
||||
</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
@ -162,7 +185,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text">
|
||||
<span class="input-group-text" data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="Team">
|
||||
<i class="bi bi-people"></i>
|
||||
</span>
|
||||
<select class="form-select" name="editMemberTeam" id="editMemberTeam">
|
||||
@ -173,7 +196,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text">
|
||||
<span class="input-group-text" data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="Section">
|
||||
<i class="bi bi-layers"></i>
|
||||
</span>
|
||||
<select class="form-select" name="editMemberSection" id="editMemberSection">
|
||||
@ -186,13 +209,10 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6 d-flex">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<span class="input-group-text" data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="Peg Number">
|
||||
<i class="bi bi-tag"></i>
|
||||
</span>
|
||||
<span class="border border-end-0 d-flex align-items-center">
|
||||
<small class="text-muted mx-2" style="margin-right: 1px;">Peg</small>
|
||||
</span>
|
||||
<input type="number" name="editMemberPeg" id="editMemberPeg" class="form-control ps-0 border-start-0 shadow-none" min="1" max="9999" value="1">
|
||||
<input type="number" name="editMemberPeg" id="editMemberPeg" class="form-control" min="1" max="9999" value="1">
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-company border-secondary-subtle ms-3" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-title="Find next available peg">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
@ -202,14 +222,13 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer border-0">
|
||||
<button type="button" class="btn btn-company" id="saveEditModal">Save Changes</button>
|
||||
<button type="button" class="btn btn-company px-4" id="saveEditModal">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% load static %}
|
||||
{% block scripts %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.full.min.js"></script>
|
||||
@ -217,6 +236,9 @@
|
||||
<script type="text/javascript">
|
||||
const getTeamsUrl = "{% url 'get-teams' %}";
|
||||
const updateMemberUrl = "{% url 'update-member' %}";
|
||||
const updateSectionUrl = "{% url 'update-section' %}"
|
||||
const updateTeamUrl = "{% url 'update-team' %}"
|
||||
const getNextIdentifierUrl = "{% url 'get-next-identifier' %}"
|
||||
const csrfMiddlewareToken = "{{ csrf_token }}";
|
||||
</script>
|
||||
<script src="{% static 'js/teams.js' %}"></script>
|
||||
|
@ -9,5 +9,8 @@ urlpatterns = [
|
||||
|
||||
# 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')
|
||||
path('update-member/', views.update_member, name='update-member'),
|
||||
path('update-section/', views.update_section, name='update-section'),
|
||||
path('update-team/', views.update_team, name='update-team'),
|
||||
path("get-next-identifier/", views.get_next_identifier, name='get-next-identifier')
|
||||
]
|
@ -5,8 +5,9 @@ from functools import reduce
|
||||
from django.shortcuts import render, redirect
|
||||
from django.http import JsonResponse
|
||||
from django.db.models import Q, Case, When, Value, IntegerField
|
||||
from django.db.utils import IntegrityError
|
||||
|
||||
from .models import Team, Member, Section
|
||||
from .models import Team, Member, Section, SectionManager, ReusableAutoField, SectionValidator
|
||||
|
||||
|
||||
def index(request):
|
||||
@ -37,7 +38,7 @@ def name_sort_key(section):
|
||||
else:
|
||||
return (1, section.name[:-1], section.name[-1])
|
||||
|
||||
def get_teams(request):
|
||||
def get_teams(request, **kwargs):
|
||||
"""Returns a JsonResponse containing a dictionary with a k/v pair for a list of teams.
|
||||
|
||||
Args:
|
||||
@ -95,6 +96,9 @@ def get_teams(request):
|
||||
response_data["sortGroups"] = sort_groups
|
||||
response_data["sortMembers"] = sort_members
|
||||
|
||||
for key, value in kwargs.items():
|
||||
response_data[key] = value
|
||||
|
||||
return JsonResponse(response_data)
|
||||
|
||||
def update_member(request):
|
||||
@ -123,3 +127,99 @@ def update_member(request):
|
||||
member.save()
|
||||
|
||||
return get_teams(request)
|
||||
|
||||
def update_section(request):
|
||||
"""Update a section, returns JsonResponse with updated teams data."""
|
||||
|
||||
if not request.POST:
|
||||
return
|
||||
|
||||
section_id = request.POST.get("sectionId")
|
||||
section_name = request.POST.get("sectionName")
|
||||
|
||||
validator = SectionValidator()
|
||||
if not validator.is_valid(section_name):
|
||||
json_response = get_teams(request, form_errors={
|
||||
"editSectionName": "This is an invalid section"
|
||||
})
|
||||
return json_response
|
||||
|
||||
if section_id == "-1":
|
||||
section = Section(name=section_name)
|
||||
else:
|
||||
section = Section.objects.get(id=section_id)
|
||||
section.name = section_name
|
||||
|
||||
try:
|
||||
section.save()
|
||||
except IntegrityError:
|
||||
json_response = get_teams(request, form_errors={
|
||||
"editSectionName": "A Section with this character already exists"
|
||||
})
|
||||
return json_response
|
||||
|
||||
return get_teams(request) # returns jsonresponse with new details
|
||||
|
||||
def update_team(request):
|
||||
"""Update a team, returns a JsonResponse with updated teams data."""
|
||||
|
||||
if not request.POST:
|
||||
return
|
||||
|
||||
team_id = request.POST.get("teamId")
|
||||
team_number = request.POST.get("teamNumber")
|
||||
|
||||
try:
|
||||
if team_id == "-1":
|
||||
team = Team.objects.create(name=team_number)
|
||||
else:
|
||||
team = Team.objects.get(id=team_id)
|
||||
team.name = team_number
|
||||
team.save()
|
||||
except IntegrityError as error:
|
||||
json_response = get_teams(request, form_errors={
|
||||
"editTeamNumber": "A Team with this number already exists"
|
||||
})
|
||||
return json_response
|
||||
|
||||
return get_teams(request)
|
||||
|
||||
def get_next_peg() -> int:
|
||||
pass
|
||||
|
||||
def get_next_section() -> str:
|
||||
|
||||
section_name = SectionManager.get_max_section()
|
||||
return SectionManager.find_next_section(section_name)
|
||||
|
||||
|
||||
def get_next_team() -> int:
|
||||
|
||||
field = ReusableAutoField
|
||||
field.model = Team
|
||||
|
||||
return field().get_default()
|
||||
|
||||
|
||||
def get_next_identifier(request):
|
||||
"""Get the next available identifer (peg, section character, etc.) for an object."""
|
||||
|
||||
if not request.POST:
|
||||
return
|
||||
|
||||
item = request.POST.get("item")
|
||||
|
||||
match item:
|
||||
case "member_peg":
|
||||
result = get_next_peg()
|
||||
|
||||
case "section_name":
|
||||
result = get_next_section()
|
||||
|
||||
case "team_number":
|
||||
result = get_next_team()
|
||||
|
||||
case _:
|
||||
raise ValueError(f"Bad identifier item: {item}")
|
||||
|
||||
return JsonResponse({"identifier": result})
|
||||
|
BIN
src/static/img/logo.webp
Normal file
BIN
src/static/img/logo.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -57,6 +57,39 @@ $(document).ready(() => {
|
||||
}
|
||||
});
|
||||
|
||||
$("#editSectionNameButton").on("click", () => {
|
||||
|
||||
$.ajax({
|
||||
url: getNextIdentifierUrl,
|
||||
type: "post",
|
||||
data: {
|
||||
"csrfmiddlewaretoken": csrfMiddlewareToken,
|
||||
"item": "section_name"
|
||||
},
|
||||
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
|
||||
success: (result) => {
|
||||
$("#editSectionName").val(result.identifier)
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$("#editTeamNumberButton").on("click", () => {
|
||||
|
||||
$.ajax({
|
||||
url: getNextIdentifierUrl,
|
||||
type: "post",
|
||||
data: {
|
||||
"csrfmiddlewaretoken": csrfMiddlewareToken,
|
||||
"item": "team_number"
|
||||
},
|
||||
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
|
||||
success: (result) => {
|
||||
$("#editTeamNumber").val(result.identifier)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("select").select2({theme: "bootstrap-5", minimumResultsForSearch: -1})
|
||||
|
||||
// load the teams with default filters
|
||||
@ -180,6 +213,10 @@ function loadTeams(groups, highlightText="", groupType) {
|
||||
$("#addMember").on("click", () => {
|
||||
openEditMemberModal(-1);
|
||||
});
|
||||
|
||||
$("#addSection").on("click", () => {
|
||||
openEditSectionModal(-1);
|
||||
});
|
||||
}
|
||||
|
||||
function fetchAndLoadTeams(search="", sortGroups="", sortMembers="") {
|
||||
@ -213,19 +250,88 @@ function teamsLoading(show=true) {
|
||||
$("#teamsLoadingSpinner").hide();
|
||||
}
|
||||
|
||||
function openEditTeamModal(teamNumber) {
|
||||
function openEditSectionModal(sectionId) {
|
||||
|
||||
// // Team data
|
||||
// const team = $(`.team[data-number='${teamNumber}']`);
|
||||
// const section = team.data("section");
|
||||
$("#editSectionNameError").hide();
|
||||
$("#editSectionModal").modal("show");
|
||||
|
||||
// // Load data to form
|
||||
// $("#editTeamTitle").text(`Team ${teamNumber}`);
|
||||
$("#saveEditSectionModal").off("click").on("click", () => {
|
||||
|
||||
// $("#editTeamNumber").val(teamNumber);
|
||||
// $('#editTeamSection').val(section);
|
||||
if(!$("#editSectionName").val().match(/^[A-Za-z]+$/)) {
|
||||
$("#editSectionName").focus();
|
||||
$("#editSectionNameError").text("Invalid section character").show();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
teamsLoading(true);
|
||||
const [search, sortGroups, sortMembers] = getFilters();
|
||||
|
||||
$.ajax({
|
||||
url: updateSectionUrl,
|
||||
type: "post",
|
||||
data: {
|
||||
"csrfmiddlewaretoken": csrfMiddlewareToken,
|
||||
"sectionId": sectionId,
|
||||
"sectionName": $("#editSectionName").val(),
|
||||
"search": search,
|
||||
"sortGroups": sortGroups,
|
||||
"sortMembers": sortMembers
|
||||
},
|
||||
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
|
||||
success: (result) => {
|
||||
|
||||
teamsLoading(false);
|
||||
loadTeams(result.groups, search, result.sortGroups);
|
||||
|
||||
if (!result.form_errors) {
|
||||
$("#editSectionModal").modal("hide");
|
||||
}
|
||||
else {
|
||||
$("#editSectionName").focus();
|
||||
$("#editSectionNameError").text(result.form_errors.editSectionName).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function openEditTeamModal(teamId) {
|
||||
|
||||
$("#editTeamModal").modal("show");
|
||||
|
||||
$("#saveEditTeamModal").off("click").on("click", () => {
|
||||
teamsLoading(true);
|
||||
|
||||
const [search, sortGroups, sortMembers] = getFilters()
|
||||
|
||||
$.ajax({
|
||||
url: updateTeamUrl,
|
||||
type: "post",
|
||||
data: {
|
||||
"csrfmiddlewaretoken": csrfMiddlewareToken,
|
||||
"teamId": teamId,
|
||||
"teamNumber": $("#editTeamNumber").val(),
|
||||
"search": search,
|
||||
"sortGroups": sortGroups,
|
||||
"sortMembers": sortMembers
|
||||
},
|
||||
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
|
||||
success: (result) => {
|
||||
|
||||
teamsLoading(false);
|
||||
loadTeams(result.groups, search, result.sortGroups);
|
||||
|
||||
if (!result.form_errors) {
|
||||
$("#editTeamModal").modal("hide");
|
||||
}
|
||||
else {
|
||||
$("#editTeamNumber").focus();
|
||||
$("#editTeamNumberError").text(result.form_errors.editTeamNumber).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function openEditMemberModal(memberId) {
|
||||
@ -271,7 +377,9 @@ function openEditMemberModal(memberId) {
|
||||
$("#editMemberModal").modal("show");
|
||||
|
||||
// Update the submit button
|
||||
$("#saveEditModal").off("click").on("click", () => { saveEditMemberModal(memberId); });
|
||||
$("#saveEditModal").off("click").on("click", () => {
|
||||
alert("you pressed save member");
|
||||
});
|
||||
}
|
||||
|
||||
function saveEditMemberModal(memberId) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user