Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Student Preference Edit #14

Merged
merged 3 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions server/forms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from os import abort
import re

from flask_wtf import FlaskForm
Expand Down Expand Up @@ -78,6 +79,14 @@ class DeleteStudentForm(FlaskForm):
submit = SubmitField('delete by emails')


class EditStudentForm(FlaskForm):
email = StringField('email', [Email()])
wants = StringField('wants')
avoids = StringField('avoids')
submit = SubmitField('make edits')
cancel = SubmitField('cancel')


class AssignForm(FlaskForm):
submit = SubmitField('assign')

Expand Down
38 changes: 38 additions & 0 deletions server/templates/edit_student.html.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends 'base.html.j2' %}
{% import 'macros.html.j2' as macros with context %}

{% block body %}
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--12-col">
<h5>Update Profile for {{ student.name }} </h5>
</div>

{% call macros.form(form) %}
<div class="mdl-cell mdl-cell--10-col delist">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
{{ form.wants(class="mdl-textfield__input", type="text", id="wants") }}
<label class="mdl-textfield__label" for="wants">New Wants</label>
</div>
</div>
<div class="mdl-cell mdl-cell--10-col delist">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
{{ form.avoids(class="mdl-textfield__input", type="text", id="avoids") }}
<label class="mdl-textfield__label" for="avoids">New Avoids</label>
</div>
</div>
<div class="mdl-cell mdl-cell--10-col delist">
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
{{ form.email(class="mdl-textfield__input", type="Email", id="email") }}
<label class="mdl-textfield__label" for="email">New Email</label>
</div>
</div>
<div class="form-buttons">
{{ form.submit(class="mdl-button mdl-js-button mdl-button--raised") }}
</div>
<div class="form-buttons">
{{ form.cancel(class="mdl-button mdl-js-button mdl-button--raised") }}
</div>
{% endcall %}
</div>
</div>
{% endblock %}
6 changes: 5 additions & 1 deletion server/templates/students.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<th class="sort mdl-data-table__cell--non-numeric" data-sort="sid" style="text-align: center;">Student ID</th>
<th class="sort mdl-data-table__cell--non-numeric" data-sort="canvas_id" style="text-align: center;">Canvas ID</th>
<th class="sort mdl-data-table__cell--non-numeric" data-sort="assignment" style="text-align: center;">Seat</th>
<th class="sort mdl-data-table__cell--non-numeric" data-sort="assignment" style="text-align: center;">Edit</th>
<th class="mdl-data-table__cell--non-numeric" style="text-align: center;">Delete</th>
</tr>
</thead>
Expand All @@ -59,9 +60,12 @@
{{ seat.room.display_name }} {{ seat.name }}
</a>
{% else %}
<span class="assignment" style="text-align: center;">&mdash;</span>
<span class="assignment" style="text-align: center;">NOT SET<br>Wants: {{ student.wants }}<br>Avoids: {{ student.avoids }}</span>
{% endif %}
</td>
<td class="mdl-data-table__cell--non-numeric" style="text-align: center;">
<div class="material-icons" style="text-align: center; margin: 0; cursor: pointer;" onclick="location.href = '{{ url_for('edit_student', exam=exam, canvas_id=student.canvas_id) }}';" style="float: right;">edit</div>
</td>
<td class="mdl-data-table__cell--non-numeric" style="text-align: center;">
<div class="material-icons" style="text-align: center; margin: 0; cursor: pointer;" onclick="location.href = '{{ url_for('delete_student', exam=exam, canvas_id=student.canvas_id) }}';" style="float: right;">clear</div>
</td>
Expand Down
33 changes: 31 additions & 2 deletions server/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from flask_login import current_user, login_required

from server import app
from server.models import db, Exam, Room, Seat, Student
from server.models import SeatAssignment, db, Exam, Room, Seat, Student
from server.forms import ExamForm, RoomForm, ChooseRoomForm, ImportStudentFromSheetForm, \
ImportStudentFromCanvasRosterForm, DeleteStudentForm, AssignForm, EmailForm
ImportStudentFromCanvasRosterForm, DeleteStudentForm, AssignForm, EmailForm, EditStudentForm
from server.services.auth import google_oauth
import server.services.canvas as canvas_client
from server.services.email import email_students
Expand Down Expand Up @@ -303,6 +303,35 @@
return render_template('student.html.j2', exam=exam, student=student)


@app.route('/<exam:exam>/students/<string:canvas_id>/edit', methods=['GET', 'POST'])
def edit_student(exam, canvas_id):
student = Student.query.filter_by(

Check warning on line 308 in server/views.py

View check run for this annotation

Codecov / codecov/patch

server/views.py#L308

Added line #L308 was not covered by tests
exam_id=exam.id, canvas_id=canvas_id).first_or_404()
if not student:
abort(404, "Student not found.")
form = EditStudentForm()
orig_wants_set = set(student.wants)
orig_avoids_set = set(student.avoids)
if request.method == 'GET':
form.wants.data = ",".join(orig_wants_set)
form.avoids.data = ",".join(orig_avoids_set)
form.email.data = student.email
if form.validate_on_submit():
if 'cancel' in request.form:
return redirect(url_for('students', exam=exam))
new_wants_set = set(re.split(r'\s|,', form.wants.data))
new_avoids_set = set(re.split(r'\s|,', form.avoids.data))
student.wants = new_wants_set
student.avoids = new_avoids_set

Check warning on line 325 in server/views.py

View check run for this annotation

Codecov / codecov/patch

server/views.py#L310-L325

Added lines #L310 - L325 were not covered by tests
# if wants or avoids changed, delete original assignment
if orig_wants_set != new_wants_set or orig_avoids_set != new_avoids_set:
SeatAssignment.query.filter_by(student_id=student.id).delete()
student.email = form.email.data
db.session.commit()
return redirect(url_for('students', exam=exam))
return render_template('edit_student.html.j2', exam=exam, form=form, student=student)

Check warning on line 332 in server/views.py

View check run for this annotation

Codecov / codecov/patch

server/views.py#L327-L332

Added lines #L327 - L332 were not covered by tests


@app.route('/<exam:exam>/students/<string:canvas_id>/delete', methods=['GET', 'DELETE'])
def delete_student(exam, canvas_id):
student = Student.query.filter_by(
Expand Down