Skip to content

Commit 780b798

Browse files
authored
Integrate courses with frontend (#126)
* Course and sections appear in create-ticket page * Remove useless text in base.html * Trying to check if section is in course * Sections and courses checked on backend, and view_tickets integration * Ignoring C901 linting warning * Fix course and section name not showing up in view tickets
1 parent b9b0d7e commit 780b798

17 files changed

+315
-164
lines changed

portal/.flake8

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22
exclude = __pycache__,templates,static
33
max-complexity = 10
44
max-line-length = 160
5-
ignore = H903, E266, D203, H306, E302, F401, E201, E202, E711
5+
6+
# TODO: Ignoring C901 temporarily until Flask-WTF is integrated
7+
ignore = H903, E266, D203, H306, E302, F401, E201, E202, E711, C901
68
indent-size=4

portal/app/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
from sqlalchemy.exc import IntegrityError
88

99
from .model import Mode
10+
from .model import Course
1011
from .model import Status
12+
from .model import Section
1113
from .model import Permission
1214
from .model import ProblemType
1315

@@ -125,10 +127,12 @@ def _read_in_config_data():
125127
def _setup_jinja_globals(app: Flask):
126128
app.jinja_env.globals['current_user'] = current_user
127129
app.jinja_env.globals['Mode'] = Mode
130+
app.jinja_env.globals['Course'] = Course
128131
app.jinja_env.globals['Status'] = Status
132+
app.jinja_env.globals['Section'] = Section
129133
app.jinja_env.globals['Permission'] = Permission
130-
app.jinja_env.globals['ConfigData'] = _read_in_config_data()
131134
app.jinja_env.globals['ProblemType'] = ProblemType
135+
app.jinja_env.globals['ConfigData'] = _read_in_config_data()
132136

133137
from .blueprints.auth import build_auth_url
134138
app.jinja_env.globals['build_auth_url'] = build_auth_url

portal/app/blueprints/admin.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -601,11 +601,11 @@ def add_professor():
601601
elif str_empty(lastName):
602602
flash('Could not add professor, last name must not be empty!', category='error')
603603
else:
604-
# check if professor already exists in DB, store all lower so checks against caps doesn't happen
605-
tmpProfessor = Professor.query.filter_by(first_name=firstName.lower(), last_name=lastName.lower()).first()
604+
# check if professor already exists in DB, store all capitalized so checks against caps doesn't happen
605+
tmpProfessor = Professor.query.filter_by(first_name=firstName.capitalize(), last_name=lastName.capitalize()).first()
606606
if tmpProfessor is None:
607-
# create professor and add it to DB, store as lower
608-
newProfessor = Professor(firstName.lower(), lastName.lower())
607+
# create professor and add it to DB, store as capitalized
608+
newProfessor = Professor(firstName.capitalize(), lastName.capitalize())
609609
db.session.add(newProfessor)
610610
db.session.commit()
611611
flash('Professor added successfully!', category='success')
@@ -645,8 +645,8 @@ def remove_professor():
645645
@permission_required(Permission.Admin)
646646
def edit_professor():
647647
professor_id = strip_or_none(request.form.get("professorID"))
648-
newFName = strip_or_none(request.form.get("fnameUpdate")).lower()
649-
newLName = strip_or_none(request.form.get("lnameUpdate")).lower()
648+
newFName = strip_or_none(request.form.get("fnameUpdate")).capitalize()
649+
newLName = strip_or_none(request.form.get("lnameUpdate")).capitalize()
650650

651651
try:
652652
professor: Professor = Professor.query.get(professor_id)
@@ -664,12 +664,12 @@ def edit_professor():
664664
flash('Could not update professor, last name cannot be empty!', category='error')
665665

666666
else:
667-
tmpProfessor = Professor.query.filter_by(first_name=newFName.lower(), last_name=newLName.lower()).first()
667+
tmpProfessor = Professor.query.filter_by(first_name=newFName.capitalize(), last_name=newLName.capitalize()).first()
668668
if tmpProfessor is None:
669669
if newFName != professor.first_name:
670-
professor.first_name = newFName.lower()
670+
professor.first_name = newFName.capitalize()
671671
if newLName != professor.last_name:
672-
professor.last_name = newLName.lower()
672+
professor.last_name = newLName.capitalize()
673673
db.session.commit()
674674
flash("Professor updated successfully!", category='success')
675675
else:
@@ -747,7 +747,7 @@ def add_section():
747747
db.session.commit()
748748
flash('Section added successfully!', category='success')
749749
else:
750-
flash("Section " + sectionNum + " for the course '" + course.course_name + "' already exists in DB!", category='error')
750+
flash(f'The section already exists in this course!', category='error')
751751

752752
return redirect(url_for('admin.view_sections'))
753753

portal/app/blueprints/views.py

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from app.model import Message
1919
from app.model import ProblemType
2020
from app.model import Course
21+
from app.model import Section
2122
from app.model import User
2223

2324
from datetime import datetime
@@ -139,11 +140,23 @@ def edit_ticket():
139140
ticketID = request.form.get("ticketIDModal")
140141
ticket = Ticket.query.get(ticketID)
141142

142-
if ticket is not None:
143-
_attempt_edit_ticket(ticket)
143+
try:
144+
if ticket is not None:
145+
_attempt_edit_ticket(ticket)
146+
147+
else:
148+
flash('Could not edit ticket. Ticket not found in database.', category='error')
149+
150+
except IntegrityError:
151+
db.session.rollback()
152+
flash('Could not updated ticket, invalid data', category='error')
153+
154+
except Exception as e:
155+
flash('Could not updated ticket, unknown reason', category='error')
156+
print(f'Failed to updated ticket: {e}', file=sys.stderr)
144157

145158
else:
146-
flash('Could not edit ticket. Ticket not found in database.', category='error')
159+
flash('Ticket updated successfully!', category='success')
147160

148161
return redirect(url_for('views.view_tickets'))
149162

@@ -222,12 +235,15 @@ def _attempt_create_ticket(form: ImmutableMultiDict):
222235
email = strip_or_none(form.get("email"))
223236
name = strip_or_none(form.get("fullname"))
224237

225-
course = strip_or_none(form.get("course"))
226-
section = strip_or_none(form.get("section"))
238+
course_id = strip_or_none(form.get("course"))
239+
section_id = strip_or_none(form.get("section"))
227240
assignment = strip_or_none(form.get("assignment"))
228241
question = strip_or_none(form.get("question"))
229242
problem_id = strip_or_none(form.get("problem"))
243+
230244
problem: ProblemType = ProblemType.query.get(problem_id)
245+
course: Course = Course.query.get(course_id)
246+
section: Section = Section.query.get(section_id)
231247

232248
if str_empty(email):
233249
flash('Could not submit ticket, email must not be empty!', category='error')
@@ -244,8 +260,11 @@ def _attempt_create_ticket(form: ImmutableMultiDict):
244260
elif problem_id is not None and not problem:
245261
flash('Could not submit ticket, problem type is not valid!', category='error')
246262

247-
# TODO: Check if course is a valid from a list of options
248-
# TODO: Check if section is valid from a list of options
263+
elif course_id is not None and not course:
264+
flash('Could not submit ticket, course is not valid!', category='error')
265+
266+
elif (section_id is not None and not section) or (course and section not in course.sections):
267+
flash('Could not submit ticket, section is not valid!', category='error')
249268

250269
else:
251270
mode_val = strip_or_none(form.get("mode"))
@@ -259,34 +278,43 @@ def _attempt_create_ticket(form: ImmutableMultiDict):
259278
flash('Could not submit ticket, must select a valid mode!', category='error')
260279

261280
else:
262-
return Ticket(email, name, course, section, assignment, question, problem_id, mode)
281+
return Ticket(email, name, course_id, section_id, assignment, question, problem_id, mode)
263282

264283
def _attempt_edit_ticket(ticket: Ticket):
265-
# get info back from popup modal form
266-
course = strip_or_none(request.form.get("courseField"))
267-
section = strip_or_none(request.form.get("sectionField"))
284+
# TODO: Need to produce error messages!!
285+
286+
course_id = strip_or_none(request.form.get("courseField"))
287+
section_id = strip_or_none(request.form.get("sectionField"))
268288
assignment = strip_or_none(request.form.get("assignmentNameField"))
269289
question = strip_or_none(request.form.get("specificQuestionField"))
270290
primaryTutor = strip_or_none(request.form.get("primaryTutorInput"))
271291
tutorNotes = strip_or_none(request.form.get("tutorNotes"))
272292
wasSuccessful = strip_or_none(request.form.get("successfulSession"))
273293
problem_id = strip_or_none(request.form.get("problemTypeField"))
294+
274295
problem: ProblemType = ProblemType.query.get(problem_id)
296+
new_course: Course = Course.query.get(course_id)
297+
section: Section = Section.query.get(section_id)
298+
299+
# Get the course of the current section
300+
current_course: Course = Course.query.get(ticket.course)
275301

276302
# check for change in values from edit
277-
if course:
303+
if course_id and new_course:
278304
# new info for course came back, update it for current ticket
279-
ticket.course = course
305+
ticket.course = new_course.id
306+
ticket.section = new_course.sections[0].id if len(new_course.sections) > 0 else None
307+
current_course = new_course
280308

281-
if section:
309+
if section_id and section and section in current_course.sections:
282310
# new info for section came back, update it for current ticket
283-
ticket.section = section
311+
ticket.section = section.id
284312

285-
if assignment != ticket.assignment_name:
313+
if assignment and assignment != ticket.assignment_name:
286314
# new info for assignment came back, update it for current ticket
287315
ticket.assignment_name = assignment
288316

289-
if question != ticket.specific_question:
317+
if question and question != ticket.specific_question:
290318
# new info for question came back, update it for current ticket
291319
ticket.specific_question = question
292320

portal/app/model.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,21 +158,17 @@ class Ticket(db.Model):
158158

159159
id = Column(Integer, primary_key=True, doc='Autonumber primary key for the ticket table.')
160160
student_email = Column(String(120), nullable=False, doc='Email of the student making the ticket.')
161-
student_name = Column(String(120), doc='The name of student making the ticket.')
162-
163-
# TODO: Need to update these columns to be foreign keys the respective tabels
164-
course = Column(String(120), doc='The specific course this ticket issue is related to.')
165-
section = Column(String(120), doc='Course section ticket issue is relating to.')
166-
#
167-
168-
assignment_name = Column(String(120), doc='Assignment the student needs help with.')
169-
specific_question = Column(Text, doc='Student question about the assignment.')
161+
student_name = Column(String(120), nullable=False, doc='The name of student making the ticket.')
162+
course = Column(String(120), nullable=False, doc='The specific course this ticket issue is related to.')
163+
section = Column(String(120), nullable=False, doc='Course section ticket issue is relating to.')
164+
assignment_name = Column(String(120), nullable=False, doc='Assignment the student needs help with.')
165+
specific_question = Column(Text, nullable=False, doc='Student question about the assignment.')
170166
problem_type = Column(Integer, db.ForeignKey('ProblemTypes.id'), doc='Type of problem the student is having.')
171167
time_created = Column(DateTime(True), nullable=False, doc='Time the ticket was created.', default=func.now())
172168
time_claimed = Column(DateTime(True), doc='Time the ticket was claimed by tutor.')
173169
time_closed = Column(DateTime(True), doc='Time the tutor marked the ticket as closed.')
174-
status = Column(Enum(Status), doc='Status of the ticket. 1=open, 2=claimed, 3=closed.', default=Status.Open)
175-
mode = Column(Enum(Mode), doc='Specifies whether the ticket was made for online or in-person help.')
170+
status = Column(Enum(Status), nullable=False, doc='Status of the ticket. 1=open, 2=claimed, 3=closed.', default=Status.Open)
171+
mode = Column(Enum(Mode), nullable=False, doc='Specifies whether the ticket was made for online or in-person help.')
176172
tutor_notes = Column(Text, doc='Space for tutors to write notes about student/ticket session.', default="")
177173
tutor_id = Column(Integer, db.ForeignKey('Users.id'), doc='Foreign key to the tutor who claimed this ticket.')
178174
successful_session = Column(Boolean, doc='T/F if the tutor was able to help the student with issue on ticket')
@@ -216,7 +212,13 @@ def calc_duration_claimed(self):
216212
return self.time_closed - self.time_claimed
217213

218214
def get_problem(self):
219-
return ProblemType.query.filter_by(id=self.problem_type).one_or_none()
215+
return ProblemType.query.get(self.problem_type)
216+
217+
def get_course(self):
218+
return Course.query.get(self.course)
219+
220+
def get_section(self):
221+
return Section.query.get(self.section)
220222

221223
def __repr__(self):
222224
return f'Ticket: {self.specific_question} ({self.student_name})'
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
let course_select = document.getElementById('course_select');
2+
let section_select = document.getElementById('section_select');
3+
4+
function update_sections()
5+
{
6+
let course_id = course_select.value;
7+
for (section of section_select.options)
8+
section.hidden = section.id !== course_id;
9+
}
10+
11+
update_sections();
12+
13+
course_select.addEventListener('change', () =>
14+
{
15+
section_select.selectedIndex = 0;
16+
section_select.hidden = false;
17+
update_sections();
18+
});

portal/app/templates/admin-professor.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ <h5 class="modal-title fs-5" id="title-label">Update Professor</h5>
105105
<tr>
106106
<th scope="col">First Name</th>
107107
<th scope="col">Last Name</th>
108-
<th scope="col">Sections</th>
109108
<th scope="col"></th>
110109
</tr>
111110
</thead>
@@ -114,7 +113,6 @@ <h5 class="modal-title fs-5" id="title-label">Update Professor</h5>
114113
<tr scope="row">
115114
<td>{{ professor.first_name.capitalize() }}</td>
116115
<td>{{ professor.last_name.capitalize() }}</td>
117-
<td>{{ professor.sections }}</td>
118116
<td>{{ remove_professor_button(professor) }} {{ edit_professor_button(professor) }}</td>
119117

120118
{{ edit_professor_modal(professor) }}

portal/app/templates/admin-sections.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,12 @@ <h5 class="modal-title fs-5" id="title-label">Update Section</h5>
251251
<tr scope="row">
252252
<td>{{ section.section_number }}</td>
253253
<td>{{ section.course }}</td>
254-
<td>{{ section.professor }}</td>
254+
<td>{{ section.professor.first_name }} {{ section.professor.last_name }}</td>
255255
<td>
256256
{% if section.section_mode == SectionMode.TotallyOnline %}
257-
N / A
257+
Online
258258
{% else %}
259-
{{ section.days_of_week }}<br>{{ section.start_time }} {{ section.end_time }}
259+
{{ section.days_of_week }}<br>{{ section.start_time }}-{{ section.end_time }}
260260
{% endif %}
261261
</td>
262262
<td>{{ section.semester_id }}</td>

portal/app/templates/admin-semester.html

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ <h5 class="modal-title fs-5" id="title-label">Update Semester</h5>
137137
<th scope="col">Season</th>
138138
<th scope="col">Start Date</th>
139139
<th scope="col">End Date</th>
140-
<th scope="col">Sections</th>
141140
<th scope="col"></th>
142141
</tr>
143142
</thead>
@@ -148,7 +147,6 @@ <h5 class="modal-title fs-5" id="title-label">Update Semester</h5>
148147
<td>{{ semester.season }}</td>
149148
<td>{{ semester.start_date }}</td>
150149
<td>{{ semester.end_date }}</td>
151-
<td>{{ semester.sections }}</td>
152150
<td>{{ remove_semester_button(semester) }} {{ edit_semester_button(semester) }}</td>
153151

154152
{{ edit_semester_modal(semester) }}

portal/app/templates/base.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,12 @@
9898
</div>
9999

100100
<!-- Footer -->
101-
<footer class="mt-auto">Blah...</footer>
101+
<footer class="mt-auto"></footer>
102102

103103
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
104+
105+
{% block scripts %}
106+
{% endblock %}
104107
</body>
105108

106109
</html>

0 commit comments

Comments
 (0)