Skip to content

Commit 97eae79

Browse files
Merge branch 'main' into main
2 parents fcdd29f + 9660664 commit 97eae79

File tree

18 files changed

+443
-208
lines changed

18 files changed

+443
-208
lines changed

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
FROM python:3.10-slim
22
LABEL maintainer="ACM at FSU <contact@fsu.acm.org>"
33

4-
ENV PYTHONUNBUFFERED 1
5-
ENV PYTHONDONTWRITEBYTECODE 1
4+
ENV PYTHONUNBUFFERED=1
5+
ENV PYTHONDONTWRITEBYTECODE=1
66

77
ARG REQUIREMENTS=requirements.txt
88

@@ -30,6 +30,7 @@ RUN pip install --no-cache-dir -r /tmp/requirements.txt \
3030
&& install -d -m 0755 -o app_user -g app_user /app/media \
3131
&& install -d -m 0755 -o app_user -g app_user /app/media/contest_files \
3232
&& install -d -m 0755 -o app_user -g app_user /app/media/ec_files \
33+
&& install -d -m 0755 -o app_user -g app_user /app/media/team_files \
3334
&& install -d -m 0755 -o app_user -g app_user /app/media/uploads
3435

3536
# Code and User Setup

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,4 @@ We welcome contributions to the project! Check out `CONTRIBUTING.md` to learn ho
100100

101101
- [Marlan McInnes-Taylor](https://github.com/mmcinnestaylor) *Creator*
102102
- [Daniel Riley](https://github.com/danielmriley)
103+
- [Preston Horne](https://github.com/prestonmhorne)

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ We welcome contributions to the project! Check out the [Contributor's Guide](htt
4545

4646
- [Marlan McInnes-Taylor](https://github.com/mmcinnestaylor) *Creator*
4747
- [Daniel Riley](https://github.com/danielmriley)
48+
- [Preston Horne](https://github.com/prestonmhorne)

src/contestadmin/forms.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,30 @@ class Meta:
4343
model = Profile
4444
fields = ["role"]
4545

46+
47+
class AccountStatusForm(forms.Form):
48+
STATUS = (
49+
(0, 'Activate'),
50+
(1, 'Deactivate')
51+
)
4652

47-
class ActivateAccountForm(forms.Form):
4853
username = forms.CharField(
4954
max_length=150,
5055
label='Username',
5156
help_text="Person's account username.")
57+
status = forms.ChoiceField(choices=STATUS)
5258

5359

5460
class DesignateFacultyTeamForm(forms.Form):
5561
teamname = forms.CharField(
5662
max_length=30,
5763
label='Team name',
5864
help_text="Name of faculty team.")
65+
66+
67+
class UpdatePasswordForm(forms.Form):
68+
username = forms.CharField(
69+
max_length=150,
70+
label='Username',
71+
help_text="Person's account username.")
72+
password = forms.CharField()

src/contestadmin/models.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,11 @@ def get_participation(self):
7171
return self.FORMAT[self.participation - 1][1]
7272
else:
7373
return 'TBA'
74+
75+
76+
def is_contest_complete(self):
77+
"""
78+
Returns true if contest is complete, false otherwise
79+
"""
80+
81+
return self.results != "" and self.results is not None

src/contestadmin/tasks.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,38 @@ def generate_ec_reports():
266266
f'Processed extra credit files for {num_courses} courses')
267267

268268

269+
@shared_task
270+
def generate_team_csvs():
271+
"""
272+
Celery task which creates CSV files containing team data per division.
273+
"""
274+
275+
for division in Team.DIVISION:
276+
if division[0] == 1: # Upper
277+
team_file = f"{MEDIA_ROOT}/team_files/upper.csv"
278+
else: # Lower
279+
team_file = f"{MEDIA_ROOT}/team_files/lower.csv"
280+
281+
with open(team_file, 'w', newline='') as team_csv:
282+
writer = csv.writer(
283+
team_csv, delimiter=',', quoting=csv.QUOTE_MINIMAL)
284+
285+
# File header
286+
writer.writerow(['team_division', 'team_name', 'questions_answered', 'domjudge_id', 'team_active', 'team_members'])
287+
288+
# Team data
289+
teams = Team.objects.filter(division=division[0])
290+
for team in teams:
291+
writer.writerow([
292+
team.get_division_code(),
293+
team.name,
294+
team.questions_answered,
295+
team.contest_id,
296+
'T' if team.is_active() else 'F',
297+
'_'.join(team.get_members())
298+
])
299+
300+
269301
@shared_task
270302
def email_faculty(domain):
271303
"""

src/contestadmin/templates/contestadmin/dashboard.html

Lines changed: 92 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ <h1 class="text-center">Contest Dashboard</h1>
2525
<i class="fa-solid fa-clock-rotate-left fa-fw"></i> Pre-Contest
2626
</div>
2727
<div class="card-body overflow-auto">
28+
<div class="row justify-content-center">
29+
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#walkinModal"> <i class="fa-solid fa-person-walking fa-fw"></i> Create Walk-in teams</button>
30+
</div>
2831
<div class="row justify-content-center">
2932
<a class="btn btn-primary btn-sm my-1" href="{% url 'gen_dj_files' %}" onclick="return confirm('Are you certain you want to generate the DOMjudge files?');"><i class="fa-solid fa-file-circle-plus fa-fw"></i> Generate DOMjudge TSVs</a>
3033
{% if dj_files_available %}
@@ -73,7 +76,6 @@ <h1 class="text-center">Contest Dashboard</h1>
7376
</div>
7477
<div class="card-body overflow-auto">
7578
<div class="row justify-content-center">
76-
7779
{% if dj_results_processed %}
7880
<!--<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#generateEcReportsModal">Generate Reports</button>-->
7981
<a class="btn btn-primary btn-sm my-1" href="{% url 'gen_ec_reports' %}" onclick="return confirm('Are you certain you want to generate the extra credit files?');"><i class="fa-solid fa-file-circle-plus fa-fw"></i> Generate Reports</a>
@@ -101,15 +103,34 @@ <h1 class="text-center">Contest Dashboard</h1>
101103
<!-- Contest tools card -->
102104
<div class="card mt-4 border-secondary">
103105
<div class="card-header font-weight-bold bg-secondary text-white">
104-
<i class="fa-solid fa-wrench fa-fw"></i> Contest Tools
106+
<i class="fa-solid fa-wrench fa-fw"></i> Tools
105107
</div>
106108
<div class="card-body overflow-auto">
107-
<div class="row justify-content-center">
108-
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#walkinModal"> <i class="fa-solid fa-person-walking fa-fw"></i> Create Walk-in teams</button>
109+
<div class="row">
110+
<div class="col-lg-6">
111+
<div class="row justify-content-center">
112+
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#accountStatusModal"><i class="fa-solid fa-user-gear fa-fw"></i> Update Account Status</button>
113+
</div>
114+
<div class="row justify-content-center">
115+
<a class="btn btn-primary btn-sm my-1" href="{% url 'generate_team_csvs' %}" onclick="return confirm('Are you certain you want to generate the team data CSVs?');"><i class="fa-solid fa-file-circle-plus fa-fw"></i> Generate Team CSVs</a>
116+
{% if team_csvs_available %}
117+
<a class="btn text-dark" href="{% url 'download_team_csvs' %}" role="button"><i class="fa fa-download fa-md" aria-hidden="true"></i></a>
118+
{% else %}
119+
<a class="btn text-secondary disabled" href="#" role="button"><i class="fa fa-download fa-md" aria-hidden="true"></i></a>
120+
{% endif %}
121+
</div>
122+
</div>
123+
<div class="col-lg-6">
124+
<div class="row justify-content-center">
125+
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#facultyTeamModal"><i
126+
class="fa-solid fa-chalkboard-user fa-fw"></i> Designate Faculty Team</button>
127+
</div>
128+
<div class="row justify-content-center">
129+
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#checkinModal"><i class="fa-solid fa-robot fa-fw"></i> Check in/out Users</button>
130+
</div>
131+
</div>
109132
</div>
110-
<div class="row justify-content-center">
111-
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#checkinModal"><i class="fa-solid fa-robot fa-fw"></i> Check in/out Users</button>
112-
</div>
133+
113134
</div>
114135
</div>
115136
<!-- Contest tools card end -->
@@ -142,17 +163,22 @@ <h1 class="text-center">Contest Dashboard</h1>
142163
<!-- Account tools card -->
143164
<div class="card mt-4 border-secondary">
144165
<div class="card-header font-weight-bold bg-secondary text-white">
145-
<i class="fa-solid fa-wrench fa-fw"></i> Account Tools
166+
<i class="fa-solid fa-user-shield fa-fw"></i> Change User Password
146167
</div>
147-
<div class="card-body overflow-auto">
148-
<div class="row justify-content-center">
149-
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#activateAccountModal"><i class="fa-solid fa-user-check fa-fw"></i> Activate User Account</button>
168+
<form method="post" onSubmit="return confirm('Are you certain you want to update this user password?');">
169+
<div class="card-body overflow-auto">
170+
{% csrf_token %}
171+
<div class="form-group">
172+
{{ update_password_form.username | placeholder:"Username" }}
173+
</div>
174+
<div class="form-group">
175+
{{ update_password_form.password | placeholder:"New password" }}
176+
</div>
150177
</div>
151-
<div class="row justify-content-center">
152-
<button type="button" class="btn btn-primary btn-sm my-1" data-toggle="modal" data-target="#facultyTeamModal"><i
153-
class="fa-solid fa-chalkboard-user fa-fw"></i> Designate Faculty Team</button>
178+
<div class="card-footer">
179+
<button class="btn btn-primary btn-sm" type="submit">Save</button>
154180
</div>
155-
</div>
181+
</form>
156182
</div>
157183
<!-- Account tools card end -->
158184
</div>
@@ -206,54 +232,57 @@ <h1 class="text-center">Contest Dashboard</h1>
206232
<!-- Discord Control deck end -->
207233

208234
<!-- Volunteer Summary card -->
209-
<div class="card mt-4 mb-3 border-secondary">
210-
<div class="card-header font-weight-bold bg-secondary text-white">
211-
<i class="fa-solid fa-handshake-simple fa-fw"></i> Volunteers
212-
</div>
213-
<div class="card-body overflow-auto">
214-
<div class="row justify-content-center">
215-
<div class="col-12">
216-
<div class="table-responsive">
217-
<table class="table table-sm">
218-
<thead class="thead-light">
219-
<tr>
220-
<th scope="col">Role</th>
221-
<th scope="col">Name</th>
222-
<th scope="col" class="text-center">Checked-in</th>
223-
<th scope="col" class="text-center">Added Courses</th>
224-
225-
</tr>
226-
</thead>
227-
<tbody>
228-
{% for volunteer in volunteers %}
229-
<tr>
230-
<td>{{ volunteer.get_role }}</td>
231-
232-
<td>{{ volunteer.user.get_full_name }}</td>
235+
<div id="accordionVolunteer">
236+
<div class="card mt-4 mb-3 border-secondary">
237+
<div class="card-header font-weight-bold bg-secondary text-white" data-toggle="collapse" data-target="#collapseVolunteer" aria-expanded="true" aria-controls="collapseVolunteer" style="cursor: pointer;">
238+
<i class="fa-solid fa-handshake-simple fa-fw"></i> Volunteers
239+
</div>
240+
<div id="collapseVolunteer" class="collapse" data-parent="#accordionVolunteer">
241+
<div class="card-body overflow-auto">
242+
<div class="row justify-content-center">
243+
<div class="col-12">
244+
<div class="table-responsive">
245+
<table class="table table-sm">
246+
<thead class="thead-light">
247+
<tr>
248+
<th scope="col">Role</th>
249+
<th scope="col">Name</th>
250+
<th scope="col" class="text-center">Checked-in</th>
251+
<th scope="col" class="text-center">Added Courses</th>
252+
253+
</tr>
254+
</thead>
255+
<tbody>
256+
{% for volunteer in volunteers %}
257+
<tr>
258+
<td>{{ volunteer.get_role }}</td>
259+
260+
<td>{{ volunteer.user.get_full_name }}</td>
233261

234-
{% if volunteer.checked_in %}
235-
<td class="text-center">Yes</td>
236-
{% else %}
237-
<td class="text-center">No</td>
238-
{% endif %}
262+
{% if volunteer.checked_in %}
263+
<td class="text-center">Yes</td>
264+
{% else %}
265+
<td class="text-center">No</td>
266+
{% endif %}
239267

240-
{% if volunteer.has_courses %}
241-
<td class="text-center">Yes</td>
242-
{% else %}
243-
<td class="text-center">No</td>
244-
{% endif %}
245-
</tr>
246-
{% endfor %}
247-
</tbody>
248-
</table>
268+
{% if volunteer.has_courses %}
269+
<td class="text-center">Yes</td>
270+
{% else %}
271+
<td class="text-center">No</td>
272+
{% endif %}
273+
</tr>
274+
{% endfor %}
275+
</tbody>
276+
</table>
277+
</div>
278+
</div>
249279
</div>
250280
</div>
251281
</div>
252282
</div>
253283
</div>
254284
<!-- Volunteer Summary card end -->
255285

256-
257286
<!-- Create Walk-in Teams Modal -->
258287
<div class="modal fade" id="walkinModal" tabindex="-1" role="dialog"
259288
aria-labelledby="confirmClearModalCenterTitle" aria-hidden="true">
@@ -290,7 +319,6 @@ <h5 class="mb-0">{{ field.label_tag }}</h5>
290319
</div>
291320
<!-- End Create Walk-in Teams Modal -->
292321

293-
294322
<!-- Checkin/Checkout Users Modal -->
295323
<div class="modal fade" id="checkinModal" tabindex="-1" role="dialog" aria-labelledby="confirmClearModalCenterTitle"
296324
aria-hidden="true">
@@ -326,20 +354,22 @@ <h5 class="modal-title" id="confirmClearModalLongTitle">Check in/out Users</h5>
326354
</div>
327355
<!-- End Create Walk-in Teams Modal -->
328356

329-
330-
<!-- Activate Account Modal -->
331-
<div class="modal fade" id="activateAccountModal" tabindex="-1" role="dialog"
357+
<!-- Account Status Modal -->
358+
<div class="modal fade" id="accountStatusModal" tabindex="-1" role="dialog"
332359
aria-labelledby="confirmClearModalCenterTitle" aria-hidden="true">
333360
<div class="modal-dialog modal-dialog-centered" role="document">
334361
<div class="modal-content">
335362
<div class="modal-header">
336-
<h5 class="modal-title" id="confirmClearModalLongTitle">Activate User Account</h5>
363+
<h5 class="modal-title" id="confirmClearModalLongTitle">Update Account Status</h5>
337364
</div>
338-
<form method="post" onSubmit="return confirm('Are you certain you want to activate this account?');">
365+
<form method="post" onSubmit="return confirm('Are you certain you want to update this account?');">
339366
<div class="modal-body overflow-auto">
340367
{% csrf_token %}
341368
<div class="form-group">
342-
{{ activate_account_form.username | placeholder:"Username"}}
369+
{{ account_status_form.username | placeholder:"Username" }}
370+
</div>
371+
<div class="form-group">
372+
{{ account_status_form.status }}
343373
</div>
344374
</div>
345375
<div class="card-footer">
@@ -350,8 +380,7 @@ <h5 class="modal-title" id="confirmClearModalLongTitle">Activate User Account</h
350380
</div>
351381
</div>
352382
</div>
353-
<!-- End Activate Account Modal -->
354-
383+
<!-- End Account Status Modal -->
355384

356385
<!-- Designate Faculty Team Modal -->
357386
<div class="modal fade" id="facultyTeamModal" tabindex="-1" role="dialog"

0 commit comments

Comments
 (0)