Skip to content

Commit

Permalink
#A15. As Admin, I would like to be able to view the participants of a…
Browse files Browse the repository at this point in the history
… hackathon (#153)
  • Loading branch information
stefdworschak authored Feb 24, 2021
1 parent 0f89acb commit d10177a
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 2 deletions.
25 changes: 25 additions & 0 deletions hackathon/migrations/0038_auto_20210224_1521.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.1.3 on 2021-02-24 15:21

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('hackathon', '0037_hackathon_teamsize'),
]

operations = [
migrations.AlterField(
model_name='hackathon',
name='judges',
field=models.ManyToManyField(blank=True, related_name='judged_hackathons', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='hackathon',
name='participants',
field=models.ManyToManyField(blank=True, related_name='participated_hackathons', to=settings.AUTH_USER_MODEL),
),
]
4 changes: 2 additions & 2 deletions hackathon/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ class Hackathon(models.Model):
# users could be the judges of more than one Hackathon: Many to Many
judges = models.ManyToManyField(User,
blank=True,
related_name='hackathon_judges')
related_name='judged_hackathons')
# Hackathons can have multiple participants judges and
# users could be participating in more than one Hackathon: Many to Many
participants = models.ManyToManyField(User,
blank=True,
related_name='hackathon_participants')
related_name='participated_hackathons')
# Hackathons can have multiple score categories and score categories
# Can belong to multiple hackahtons: Many to Many
score_categories = models.ManyToManyField(
Expand Down
74 changes: 74 additions & 0 deletions hackathon/templates/hackathon/hackathon_stats.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{% extends 'base.html' %}

{% block content %}

<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<div class="card-title">Hackathon Stats</div>
<div class="card-text">

<div class="row">
<div class="col-md-12 col-lg-6">
<label for="hackathonFilter">
<select id="hackathonFilter" class="form-control">
<option value="0">All Hackthons</option>
{% for hackathon in hackathons %}
<option value="{{hackathon.id}}">{{hackathon.display_name}}</option>
{% endfor %}
</select>
</label>
</div>
<div class="col-md-12 col-lg-2">
User Count: <span id="userCount">{{ users|length }}</span>
</div>
<div class="col-md-12 col-lg-4">
<button class="btn btn-primary btn-sm float-right" id="downloadUsers">Export Users</button>
</div>
</div>


<table class="table table-sm mt-5" id="usersTable">
<thead>
<tr>
<th scope="col">Slack Display Name</th>
<th scope="col">Email</th>
<th scope="col">Current LMS Module</th>
<th scope="col">Privileges</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr data-hackathons="{% for hackathon in user.participated_hackathons.all %}{{hackathon.id}},{% endfor %}">
<td>
{{ user.slack_display_name }}
</td>
<td>
{{ user.email }}
</td>
<td>
{{ user.current_lms_module }}
</td>
<td>
{% if user.is_staff and user.is_superuser %}
Superuser
{% elif user.is_staff %}
Staff
{% else %}
Participant
{% endif %}
</td>
</tr>
{% endfor %}
</table>

</div>
</div>
</div>
</div>
</div>



{% endblock %}
2 changes: 2 additions & 0 deletions hackathon/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
view_hackathon,
update_hackathon_status,
change_awards,
hackathon_stats,
)
from teams.views import change_teams

Expand All @@ -30,4 +31,5 @@
path("<int:hackathon_id>/delete", delete_hackathon,
name="delete_hackathon"),
path('enroll/', enroll_toggle, name='enroll_toggle'),
path('stats/', hackathon_stats, name='hackathon_stats'),
]
15 changes: 15 additions & 0 deletions hackathon/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.shortcuts import render, get_object_or_404, redirect, reverse
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import get_user_model
from django.core.paginator import Paginator
from django.http import JsonResponse, HttpResponse
from django.utils import timezone
Expand Down Expand Up @@ -533,3 +534,17 @@ def change_awards(request, hack_id):
"An unexpected error occurred. Please try again")
return redirect(reverse('hackathon:awards',
kwargs={'hack_id': hack_id}))


@login_required
def hackathon_stats(request):
if not request.user.is_superuser:
messages.error(request, 'You do not have access to this page.')
return reverse(reverse('hackathon:hackathon-list'))

hackathons = Hackathon.objects.all().exclude(status='deleted')
users = get_user_model().objects.all()
return render(request, 'hackathon/hackathon_stats.html', {
'hackathons': hackathons,
'users': users,
})
5 changes: 5 additions & 0 deletions static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,11 @@ img.showcase-image-edit {
max-width: none;
}

/* Hackathon Stats */
.hide-row{
display:none;
}

/* Media Queries */

@media (max-width:453px) {
Expand Down
42 changes: 42 additions & 0 deletions static/js/script.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
$(document).ready(function(){
$('.edit-image').click(setUpoadImageType);
filterUsersByHackathon();
});

function setUpoadImageType(){
Expand All @@ -8,3 +9,44 @@ function setUpoadImageType(){
$('#image-upload-type').val(imageType);
$('#image-upload-identifier').val(identifier);
}

function filterUsersByHackathon(){
$('#hackathonFilter').change(function(){
let userCount = 0;
let elementValue = $(this).val();
$('#usersTable tbody tr').each(function(){
if(elementValue == '0'){
$(this).removeClass('hide-row');
userCount++;
} else {
if($(this).data('hackathons').split(',').includes(elementValue)){
$(this).removeClass('hide-row');
userCount++;
} else {
$(this).addClass('hide-row');
}
}
});
$('#userCount').text(userCount);
});

$('#downloadUsers').click(function(){
let csvContent = '';
let rows = $('#usersTable tr:not(.hide-row)');
rows.each(function(){
let tds = $(this).children();
let rowText = [];
tds.each(function(){
rowText.push($(this).text().trim());
});
csvContent +=rowText.join(',') + '\n';
});

let link = document.createElement('a')
link.id = 'download-csv'
link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(csvContent));
link.setAttribute('download', 'user-export.csv');
document.body.appendChild(link);
document.querySelector('#download-csv').click();
});
}
1 change: 1 addition & 0 deletions templates/includes/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<a class="dropdown-item" href="{% url 'profile' %}">My Profile</a>
{% if user.is_superuser %}
<a class="dropdown-item" href="{% url 'admin:index' %}" target="_blank">Admin Panel</a>
<a class="dropdown-item" href="{% url 'hackathon:hackathon_stats' %}">Hackthon Stats</a>
{% endif %}
<a class="dropdown-item" href="{% url 'account_logout' %}">Logout</a>
{% endif %}
Expand Down

0 comments on commit d10177a

Please sign in to comment.