Corban-Lee e2ad5676c7 Crude section/teams implementation
do not merge to main, very buggy rough implementation of sorting between teams and sections. I have rewritten many areas.
2023-05-10 00:58:38 +01:00

309 lines
11 KiB
JavaScript

jQuery.expr[':'].icontains = function(a, i, m) {
return jQuery(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
$(document).ready(() => {
teamsLoading(true); // show the loading icon
// Search functionality
var searchTimeout = null;
// Bind searching to when a key is lifted on the searchbar
$("#search").keyup(() => {
clearTimeout(searchTimeout);
teamsLoading(true);
searchTimeout = setTimeout(() => {
fetchAndLoadTeams(...getFilters());
}, 500)
});
// Bind searching to the search button
$("#searchButton").on("click", () => {
fetchAndLoadTeams(...getFilters());
});
// Bind searching to the sort buttons
$("#sortForm input").on("click", function() {
const name = $(this).attr("name");
localStorage.setItem(name, $(`input[name='${name}']:checked`, "#sortForm").val());
fetchAndLoadTeams(...getFilters());
});
// Load the last saved sort settings TODO: use local storage so it only saves on one reload
const sortTeamsValue = localStorage.getItem("sortGroups");
if (sortTeamsValue !== null) {
$("#sortForm input[name='sortGroups']").val([sortTeamsValue]);
}
const sortMembersValue = localStorage.getItem("sortMembers");
if (sortMembersValue !== null) {
$("#sortForm input[name='sortMembers']").val([sortMembersValue]);
}
// Customize form validation for the edit members form
$("#editMemberForm").validate({ errorClass: "text-danger mb-2" });
// Prevent dropdowns from closing when clicking inside
$('.dropdown-menu').on('hide.bs.dropdown', function (e) {
var target = $(e.clickEvent.target);
if(target.hasClass("keepopen") || target.parents(".keepopen").length){
return false; // returning false should stop the dropdown from hiding.
}else{
return true;
}
});
// load the teams with default filters
fetchAndLoadTeams(...getFilters());
});
/**
* Returns an array of search filters in this order [search, sortTeams, sortMembers]
*
* @returns {Array} The array of filters, each filter is a string.
*/
function getFilters() {
return [
$("#search").val(),
$("input[name='sortGroups']:checked", "#sortForm").val(),
$("input[name='sortMembers']:checked", "#sortForm").val()
]
}
function loadTeams(groups, highlightText="", groupType) {
$("#teamsContainer").html(""); // Clear the previous listed teams
if (groups.length < 1) {
$("#teamsNotFound").show();
}
groupType = groupType.toUpperCase();
// Iterate over and add each 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='${group.name}'>
<h3>
<span class='fs-4'>
<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>
</button>
</h3>
<ul class='list-unstyled team-members mt-3'>
</ul>
</div>
</div>`
);
// While we have the team, iterate over and add it's members
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'>
<div
class='team-member d-flex'
data-first='${member.first}'
data-last='${member.last}'
data-member-id='${member.id}'
data-team-number='${member.team}'
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='${oppositeGroupType} ${oppositeGroupName}' data-bs-toggle='tooltip'>
${oppositeGroupName}
</div>
<div class='d-inline-block ms-2 team-member-fullname'>
${fullname}
</div>
</div>
<button type='button' class='ms-auto btn btn-light border-0 fs-6 pencil-btn align-self-center me-1 force-contents-center'>
<i class='bi bi-pencil'></i>
</button>
</div>
</li>`
)
});
});
activateTooltips(); // activate the new tooltips
// Highlight all instances where the text matches the search critera
if (!isEmptyOrSpaces(highlightText)) {
$("#teamsContainer").find('.team-member-fullname').each(function() {
var regex = new RegExp(highlightText, 'gi');
$(this).html($(this).text().replace(regex, '<span class="text-company fw-bolder border-2 border-bottom border-company">$&</span>'));
});
}
// Bind edit team modal to the edit team button
$(".team > h3 > button").on("click", function() {
$(this).addClass("active");
$("#editTeamModal").off("hidden.bs.modal").on("hidden.bs.modal", function() {
$("#teamsContainer").find(".team").find("button.active").removeClass("active");
});
openEditTeamModal($(this).parent().parent().data("number"));
});
// Bind edit member modal to the edit member button
$(".team-member button").on("click", function() {
$(this).addClass("active");
$("#editMemberModal").off("hidden.bs.modal").on("hidden.bs.modal", function() {
$("#teamsContainer").find(".team").find("button.active").removeClass("active");
});
openEditMemberModal($(this).parent().data("member-id"));
});
// Bind new member/team buttons
$("#addTeam").on("click", () => {
openEditTeamModal(-1);
});
$("#addMember").on("click", () => {
openEditMemberModal(-1);
});
}
function fetchAndLoadTeams(search="", sortGroups="", sortMembers="") {
$.ajax({
url: getTeamsUrl,
type: "post",
data: {
"csrfmiddlewaretoken": csrfMiddlewareToken,
"search": search,
"sortGroups": sortGroups,
"sortMembers": sortMembers
},
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
success: (result) => {
teamsLoading(false);
loadTeams(result.groups, search, result.sortGroups);
}
});
}
function teamsLoading(show=true) {
$("#teamsNotFound").hide()
if (show) {
$("#teamsContainer").hide();
$("#teamsLoadingSpinner").show();
return
}
$("#teamsContainer").show();
$("#teamsLoadingSpinner").hide();
}
function openEditTeamModal(teamNumber) {
// Team data
const team = $(`.team[data-number='${teamNumber}']`);
const section = team.data("section");
// Load data to form
$("#editTeamTitle").text(`Team ${teamNumber}`);
$("#editTeamNumber").val(teamNumber);
$('#editTeamSection').val(section);
$("#editTeamModal").modal("show");
}
function openEditMemberModal(memberId) {
var modalTitle = "Add Member";
var first = "";
var last = "";
var teamNumber = $(".team").map(function() { return $(this).data("number"); }).get(); // TODO: shorten this
var pegNumber = 0;
var firstPlaceholder = "Forename";
var lastPlaceholder = "Surname";
// Member data
if (memberId !== -1) {
const member = $(`.team-member[data-member-id='${memberId}']`);
first = member.data("first");
last = member.data("last");
teamNumber = member.data("team-number");
pegNumber = member.data("peg-number");
firstPlaceholder = first;
lastPlaceholder = last;
modalTitle = "Edit: " + first + " " + last
}
// Load teams as options
$("#editMemberTeam").html("");
$(".team").map(function() {
return $(this).data("number");
}).get().forEach((team) => {
$("#editMemberTeam").append($(`<option value='${team}'>Team ${team}</option>`));
});
// Load data to form
$("#editMemberName").text(modalTitle);
$("#editMemberFirstName").val(first);
$("#editMemberLastName").val(last);
$("#editMemberTeam").val(teamNumber);
$("#editMemberPeg").val(pegNumber);
$("#editMemberFirstName").attr("placeholder", firstPlaceholder);
$("#editMemberLastName").attr("placeholder", lastPlaceholder);
$("#editMemberModal").modal("show");
// Update the submit button
$("#saveEditModal").off("click").on("click", () => { saveEditMemberModal(memberId); });
}
function saveEditMemberModal(memberId) {
if (!$("#editMemberForm").valid()) {
return;
}
// Grab the updated data
const first = $("#editMemberFirstName").val();
const last = $("#editMemberLastName").val();
const teamNumber = $("#editMemberTeam").val();
const pegNumber = $("#editMemberPeg").val();
const search = $("#search").val();
teamsLoading(true);
$.ajax({
url: updateMemberUrl,
type: "post",
data: {
"csrfmiddlewaretoken": csrfMiddlewareToken,
"memberId": memberId,
"first": first,
"last": last,
"teamNumber": teamNumber,
"pegNumber": pegNumber,
"search": !isEmptyOrSpaces(search) ? search : null
},
error: (xhr, textStatus, errorThrown) => { alert(xhr + " " + textStatus + " " + errorThrown); },
success: (result) => {
teamsLoading(false);
loadTeams(result.teams, search, result.sortGroups);
$("#editMemberModal").modal("hide");
}
});
}