improved search and UI on teams page

This commit is contained in:
Corban-Lee 2023-05-06 04:09:18 +01:00
parent 0f1c839daa
commit 439ae32a79
3 changed files with 130 additions and 43 deletions

View File

@ -5,24 +5,35 @@
{% endblock title %}
{% block content %}
<div class="bg-body-secondary p-4">
<div class="bg-body p-4">
<a href="{% url 'index' %}" class="btn btn-primary px-4">Back</a>
</div>
<div class="container my-4 p-4 bg-body-secondary rounded">
<div class="row">
<div class="container my-4 p-4 pb-0 bg-body-secondary rounded">
<div class="row mb-4">
<div class="col-md-6 col-xl-8">
<h3 class="mb-4">Teams & their Members</h3>
<h3 class="mb-0">Teams &amp; Members</h3>
</div>
<div class="col-md-6 col-xl-4">
<div class="input-group mb-4 mb-md-0">
<input type="search" class="form-control" placeholder="Search" id="search">
<button type="button" class="btn border"><i class="bi bi-search"></i></button>
<input type="search" class="form-control" placeholder="Search Members" id="search">
<button type="button" class="btn border bg-body"><i class="bi bi-search"></i></button>
</div>
</div>
</div>
<div class="row" id="teamsContainer"></div>
<div class="col-12 text-center pb-4" id="teamsLoadingSpinner">
<div class="spinner-border spinner-border-lg" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div class="pb-4" id="teamsNotFound">
<div class="alert alert-danger m-0" role="alert">
No teams found under that search
</div>
</div>
</div>
<!-- Edit Modal -->
@ -60,21 +71,67 @@
{% block scripts %}
<script type="text/javascript">
jQuery.expr[':'].icontains = function(a, i, m) {
return jQuery(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
$(document).ready(() => {
loadTeams();
teamsLoading(true);
fetchAndLoadTeams();
var searchTimeout = null;
$("#search").keyup(() => {
clearTimeout(searchTimeout);
teamsLoading(true);
searchTimeout = setTimeout(() => {
loadTeams($("#search").val());
fetchAndLoadTeams($("#search").val());
}, 500)
})
})
function loadTeams(search="") {
function loadTeams(teams, highlightText="") {
$("#teamsContainer").html(""); // Clear the previous listed teams
if (teams.length < 1) {
$("#teamsNotFound").show()
}
// Iterate over and add each team
teams.forEach((team) => {
$("#teamsContainer").append(
`<div class='col-12 col-md-6 col-xl-4 mb-4'>
<div class='p-4 bg-body-tertiary rounded h-100 fluid-hover-zoom shadow-sm hover-shadow'>
<h4>${team.identifier}</h4>
<ul class='list-unstyled ul-cols-2 team-members'>
</ul>
</div>
</div>`
);
// While we have the team, iterate over and add it's members
team.members.forEach((member) => {
$("#teamsContainer").find(".team-members").last().append(
`<li>
<span
type='button'
class='team-member'
onclick='javascript:openEditModal("${member.name}");'
>
${member.name}
</span>
</li>`
)
});
});
if (highlightText) {
$("#teamsContainer").find(`.team-member:icontains('${highlightText}')`).css("color", "red")
}
}
function fetchAndLoadTeams(search) {
$.ajax({
url: "{% url 'get-teams' %}",
type: "post",
@ -82,36 +139,27 @@
"csrfmiddlewaretoken": "{{ csrf_token }}",
"search": search
},
success: (results) => {
$("#teamsContainer").html("");
for (var i = 0; i < results.teams.length; i++) {
var team = results.teams[i];
$("#teamsContainer").append(
"<div class='col-12 col-md-6 col-xl-4 mb-4'>" +
"<div class='p-4 bg-body-tertiary rounded h-100'>" +
`<h4>${team.identifier}</h4>` +
"<ul class='list-unstyled ul-cols-2 team-members'>" +
"</ul>" +
"</div>" +
"</div>"
);
for (var j = 0; j < team.members.length; j++) {
var member = team.members[j];
$("#teamsContainer").find(".team-members").last().append(
"<li>" +
`<span type='button' class='team-member' onclick='javascript:openEditModal("${member.name}");'>${member.name}</span>` +
"</li>"
);
}
}
},
error: (xhr, textStatus, errorThrown) => {
alert(errorThrown);
error: (xhr, textStatus, errorThrown) => { alert(errorThrown); },
success: (result) => {
teamsLoading(false)
loadTeams(result.teams, search);
}
});
}
function teamsLoading(show=true) {
$("#teamsNotFound").hide()
if (show) {
$("#teamsContainer").hide();
$("#teamsLoadingSpinner").show();
return
}
$("#teamsContainer").show();
$("#teamsLoadingSpinner").hide();
}
function openEditModal(name) {
var [first, last] = name.split(" ");

View File

@ -6,7 +6,6 @@ from django.shortcuts import render, redirect
from django.http import JsonResponse
from .models import Peg
from .teams_demo_test import created_teams
def index(request):
return render(request, 'index.html')
@ -38,12 +37,32 @@ def get_teams(request):
search = request.POST.get("search")
if search:
created_teams.sort(reverse=True, key=lambda team: next((
member["name"] for member in team["members"]
if search.lower() in member["name"].lower()), ""
))
else:
created_teams.sort(reverse=False, key=lambda team: team["identifier"])
from .teams_demo_test import created_teams
if search:
unfiltered_teams = created_teams.copy()
created_teams = [
team for team in unfiltered_teams
if any(
search.lower() in name for name in
[member["name"].lower() for member in team["members"]]
)
]
created_teams.sort(reverse=False, key=lambda team: team["identifier"])
return JsonResponse({"teams": created_teams})
# if not search:
# created_teams.sort(reverse=False, key=lambda team: team["identifier"])
# return JsonResponse({"teams": created_teams})
# # Create a new list only containing teams that meet the search criteria
# filtered_teams = []
# for team in created_teams:
# member_names = [member["name"].lower() for member in team["members"]]
# if any(search.lower() in name for name in member_names):
# filtered_teams.append(team)
# filtered_teams.sort(reverse=False, key=lambda team: team["identifier"])
# return JsonResponse({"teams": filtered_teams})

View File

@ -10,3 +10,23 @@
box-sizing: border-box;
padding: 5px;
}
.spinner-border-lg {
width: 3rem;
height: 3rem;
}
.fluid-hover-zoom {
transition: .3s
transform cubic-bezier(.155,1.105,.295,1.12),
.3s box-shadow,
.3s -webkit-transform cubic-bezier(.155,1.105,.295,1.12);
}
.fluid-hover-zoom:hover {
transform: scale(1.04);
}
.hover-shadow:not(:hover) {
box-shadow: none !important;
}