improved search and UI on teams page
This commit is contained in:
parent
0f1c839daa
commit
439ae32a79
@ -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 & 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(" ");
|
||||
|
@ -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})
|
||||
|
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user