Coverage for app/controllers/serviceLearning/routes.py: 28%
182 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-24 14:13 +0000
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-24 14:13 +0000
1from flask import request, render_template, g, url_for, abort, redirect, flash, session, send_from_directory, send_file, jsonify
2from werkzeug.utils import safe_join
3import os
4from peewee import *
5from app.models.user import User
6from app.models.term import Term
7from app.models.course import Course
8from app.models.courseStatus import CourseStatus
9from app.models.courseInstructor import CourseInstructor
10from app.models.courseQuestion import CourseQuestion
11from app.models.attachmentUpload import AttachmentUpload
12from app.logic.utils import selectSurroundingTerms, getFilesFromRequest
13from app.logic.fileHandler import FileHandler
14from app.logic.serviceLearningCoursesData import getServiceLearningCoursesData, withdrawProposal, renewProposal
15from app.logic.courseManagement import updateCourse, createCourse
16from app.logic.downloadFile import *
17from app.logic.courseManagement import approvedCourses
18from app.controllers.main.routes import getRedirectTarget, setRedirectTarget
19from app.controllers.serviceLearning import serviceLearning_bp
22@serviceLearning_bp.route('/serviceLearning/courseManagement', methods = ['GET'])
23@serviceLearning_bp.route('/serviceLearning/courseManagement/<username>', methods = ['GET'])
24def serviceCourseManagement(username=None):
25 if g.current_user.isStudent:
26 abort(403)
27 if g.current_user.isCeltsAdmin or g.current_user.isFaculty:
28 setRedirectTarget("/serviceLearning/courseManagement")
29 user = User.get(User.username==username) if username else g.current_user
30 courseDict = getServiceLearningCoursesData(user)
31 termList = selectSurroundingTerms(g.current_term, prevTerms=0)
32 return render_template('serviceLearning/slcManagement.html',
33 user=user,
34 courseDict=courseDict,
35 termList=termList)
36 else:
37 flash("Unauthorized to view page", 'warning')
38 return redirect(url_for('main.events', selectedTerm=g.current_term))
40@serviceLearning_bp.route('/serviceLearning/viewProposal/<courseID>', methods=['GET'])
41@serviceLearning_bp.route('/serviceLearning/editProposal/upload/<courseID>', methods=['GET'])
42@serviceLearning_bp.route('/serviceLearning/editProposal/<courseID>', methods=['GET'])
43def slcEditProposal(courseID):
44 """
45 Route for editing proposals, it will fill the form with the data found in the database
46 given a courseID.
47 """
48 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID)
49 courseInstructors = [instructor.user for instructor in instructors]
50 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors:
51 course = Course.get_by_id(courseID)
52 courseStatus = CourseStatus.get_by_id(course.status)
53 courseStatusInt = courseStatus.get_id()
54 approved = 3
55 # Condition to check the route you are comming from
56 if courseStatusInt==approved and request.path == f"/serviceLearning/editProposal/{courseID}":
57 return redirect(f"/serviceLearning/viewProposal/{courseID}")
58 else:
59 statusOfCourse = Course.select(Course.status)
60 questionData = (CourseQuestion.select().where(CourseQuestion.course == course))
61 questionanswers = [question.questionContent for question in questionData]
62 courseInstructor = CourseInstructor.select().where(CourseInstructor.course == courseID)
63 associatedAttachments = AttachmentUpload.select().where(AttachmentUpload.course == course.id)
65 filepaths = FileHandler(courseId=course.id).retrievePath(associatedAttachments)
67 terms = selectSurroundingTerms(g.current_term, 0)
68 return render_template('serviceLearning/slcNewProposal.html',
69 course = course,
70 questionanswers = questionanswers,
71 terms = terms,
72 statusOfCourse = statusOfCourse,
73 courseStatus = courseStatus,
74 courseInstructor = courseInstructor,
75 filepaths = filepaths,
76 redirectTarget=getRedirectTarget())
77 else:
78 abort(403)
81@serviceLearning_bp.route('/serviceLearning/createCourse', methods=['POST'])
82def slcCreateCourse():
83 """will give a new course ID so that it can redirect to an edit page"""
84 course = createCourse(g.current_user)
86 return redirect(url_for('serviceLearning.slcEditProposal', courseID = course.id))
88@serviceLearning_bp.route('/serviceLearning/saveExit', methods=['POST'])
89@serviceLearning_bp.route('/serviceLearning/saveProposal', methods=['POST'])
90def slcSaveContinue():
91 """Will update the the course proposal and return an empty string since ajax request needs a response
92 Also, it updates the course status as 'in progress'"""
93 course = updateCourse(request.form.copy())
95 if not course:
96 flash("Error saving changes", "danger")
97 else:
98 course.status = CourseStatus.IN_PROGRESS
99 course.save()
100 flash(f"Proposal has been saved.", "success")
101 return ""
103@serviceLearning_bp.route('/serviceLearning/newProposal', methods=['GET', 'POST'])
104def slcCreateOrEdit():
105 if request.method == "POST":
106 course = updateCourse(request.form.copy())
107 if not course:
108 flash("Error saving changes", "danger")
109 else:
110 if getRedirectTarget(False):
111 return redirect('' + getRedirectTarget(True) + '')
112 return redirect('/serviceLearning/courseManagement')
114 terms = Term.select().where(Term.year >= g.current_term.year)
115 courseData = None
116 return render_template('serviceLearning/slcNewProposal.html',
117 terms = terms,
118 courseData = courseData,
119 redirectTarget = getRedirectTarget(True))
121@serviceLearning_bp.route('/serviceLearning/approveCourse', methods=['POST'])
122def approveCourse():
123 """
124 This function updates and approves a Service-Learning Course when using the
125 approve button.
126 return: empty string because AJAX needs to receive something
127 """
129 try:
130 # We are only approving, and not updating
131 if len(request.form) == 1:
132 course = Course.get_by_id(request.form['courseID'])
134 # We have data and need to update the course first
135 else:
136 course = updateCourse(request.form.copy())
138 course.status = CourseStatus.APPROVED
139 course.save()
140 flash("Course approved!", "success")
142 except Exception as e:
143 print(e)
144 flash("Course not approved!", "danger")
145 return ""
146@serviceLearning_bp.route('/serviceLearning/unapproveCourse', methods=['POST'])
147def unapproveCourse():
148 """
149 This function updates and unapproves a Service-Learning Course when using the
150 unapprove button.
151 return: empty string because AJAX needs to receive something
152 """
154 try:
155 if len(request.form) == 1:
156 course = Course.get_by_id(request.form['courseID'])
157 else:
158 course = updateCourse(request.form.copy())
160 course.status = CourseStatus.SUBMITTED
161 course.save()
162 flash("Course unapproved!", "success")
164 except Exception as e:
165 print(e)
166 flash("Course was not unapproved!", "danger")
168 return ""
170@serviceLearning_bp.route('/updateInstructorPhone', methods=['POST'])
171def updateInstructorPhone():
172 instructorData = request.get_json()
173 (User.update(phoneNumber=instructorData[1])
174 .where(User.username == instructorData[0])).execute()
175 return "success"
177@serviceLearning_bp.route('/serviceLearning/withdraw/<courseID>', methods = ['POST'])
178def withdrawCourse(courseID):
179 try:
180 if g.current_user.isAdmin or g.current_user.isFaculty:
181 withdrawProposal(courseID)
182 flash("Course successfully withdrawn", 'success')
183 else:
184 flash("Unauthorized to perform this action", 'warning')
185 except Exception as e:
186 print(e)
187 flash("Withdrawal Unsuccessful", 'warning')
188 return ""
190@serviceLearning_bp.route('/serviceLearning/renew/<courseID>/<termID>/', methods = ['POST'])
191def renewCourse(courseID, termID):
192 """
193 This function checks to see if the user is a CELTS admin or is
194 an instructor of a course (faculty) and allows courses to be renewed.
195 :return: empty string because AJAX needs to receive something
196 """
197 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID)
198 courseInstructors = [instructor.user for instructor in instructors]
199 try:
200 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors:
201 renewedProposal = renewProposal(courseID, termID)
202 flash("Course successfully renewed", 'success')
203 return str(renewedProposal.id)
204 else:
205 flash("Unauthorized to perform this action", 'warning')
206 except Exception as e:
207 print(e)
208 flash("Renewal Unsuccessful", 'warning')
210 return "", 500
212@serviceLearning_bp.route('/serviceLearning/print/<courseID>', methods=['GET'])
213def printCourse(courseID):
214 """
215 This function will print a PDF of an SLC proposal.
216 """
217 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID)
218 courseInstructors = [instructor.user for instructor in instructors]
219 isCreator = Course.select().where(Course.createdBy == g.current_user, Course.id==courseID).exists()
220 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors or isCreator:
221 try:
222 course = Course.get_by_id(courseID)
223 pdfCourse = Course.select().where(Course.id == courseID)
224 pdfInstructor = CourseInstructor.select().where(CourseInstructor.course == courseID)
225 pdfQuestions = (CourseQuestion.select().where(CourseQuestion.course == course))
226 questionanswers = [question.questionContent for question in pdfQuestions]
228 return render_template('serviceLearning/slcFormPrint.html',
229 course = course,
230 pdfCourse = pdfCourse,
231 pdfInstructor = pdfInstructor,
232 pdfQuestions = pdfQuestions,
233 questionanswers=questionanswers
234 )
235 except Exception as e:
236 flash("An error was encountered when printing, please try again.", 'warning')
237 print(e)
238 return "", 500
239 else:
240 abort(403)
242@serviceLearning_bp.route("/uploadCourseFile", methods=['GET', "POST"])
243def uploadCourseFile():
244 try:
245 attachment = getFilesFromRequest(request)
246 courseID = request.form["courseID"]
247 addFile= FileHandler(attachment, courseId=courseID)
248 addFile.saveFiles()
249 except:
250 flash("No file selected.", "warning")
251 return redirect('/serviceLearning/editProposal/upload/'+courseID)
254@serviceLearning_bp.route("/deleteCourseFile", methods=["POST"])
255def deleteCourseFile():
256 fileData= request.form
257 courseFile=FileHandler(courseId=fileData["courseId"])
258 courseFile.deleteFile(fileData["fileId"])
259 return ""
261@serviceLearning_bp.route('/serviceLearning/downloadApprovedCourses/<termID>', methods = ['GET'])
262def downloadApprovedCourses(termID):
263 """
264 This function allows the download of csv file
265 """
266 try:
267 designator = "downloadApprovedCourses"
268 csvInfo = approvedCourses(termID)
269 fileFormat = {"headers":["Course Name", "Course Number", "Faculty", "Term", "Previously Approved Course?"]}
270 filePath = safe_join(os.getcwd(), app.config['files']['base_path'])
271 newFile = fileMaker(designator, csvInfo, "CSV", fileFormat)
272 return send_from_directory(filePath, 'ApprovedCourses.csv', as_attachment=True)
274 except Exception as e:
275 print(e)
276 return ""