Coverage for app/controllers/serviceLearning/routes.py: 28%
183 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-06-13 18:20 +0000
« prev ^ index » next coverage.py v7.2.5, created at 2023-06-13 18:20 +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 isCourseCreator = Course.select().where(Course.createdBy == g.current_user, Course.id==courseID).exists()
52 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors or isCourseCreator:
53 course = Course.get_by_id(courseID)
54 courseStatus = CourseStatus.get_by_id(course.status)
55 courseStatusInt = courseStatus.get_id()
56 approved = 3
57 # Condition to check the route you are comming from
58 if courseStatusInt==approved and request.path == f"/serviceLearning/editProposal/{courseID}":
59 return redirect(f"/serviceLearning/viewProposal/{courseID}")
60 else:
61 statusOfCourse = Course.select(Course.status)
62 questionData = (CourseQuestion.select().where(CourseQuestion.course == course))
63 questionanswers = [question.questionContent for question in questionData]
64 courseInstructor = CourseInstructor.select().where(CourseInstructor.course == courseID)
65 associatedAttachments = AttachmentUpload.select().where(AttachmentUpload.course == course.id)
67 filepaths = FileHandler(courseId=course.id).retrievePath(associatedAttachments)
69 terms = selectSurroundingTerms(g.current_term, 0)
70 return render_template('serviceLearning/slcNewProposal.html',
71 course = course,
72 questionanswers = questionanswers,
73 terms = terms,
74 statusOfCourse = statusOfCourse,
75 courseStatus = courseStatus,
76 courseInstructor = courseInstructor,
77 filepaths = filepaths,
78 redirectTarget=getRedirectTarget())
79 else:
80 abort(403)
83@serviceLearning_bp.route('/serviceLearning/createCourse', methods=['POST'])
84def slcCreateCourse():
85 """will give a new course ID so that it can redirect to an edit page"""
86 course = createCourse(g.current_user)
88 return redirect(url_for('serviceLearning.slcEditProposal', courseID = course.id))
90@serviceLearning_bp.route('/serviceLearning/saveExit', methods=['POST'])
91@serviceLearning_bp.route('/serviceLearning/saveProposal', methods=['POST'])
92def slcSaveContinue():
93 """Will update the the course proposal and return an empty string since ajax request needs a response
94 Also, it updates the course status as 'in progress'"""
95 course = updateCourse(request.form.copy())
97 if not course:
98 flash("Error saving changes", "danger")
99 else:
100 course.status = CourseStatus.IN_PROGRESS
101 course.save()
102 flash(f"Proposal has been saved.", "success")
103 return ""
105@serviceLearning_bp.route('/serviceLearning/newProposal', methods=['GET', 'POST'])
106def slcCreateOrEdit():
107 if request.method == "POST":
108 course = updateCourse(request.form.copy())
109 if not course:
110 flash("Error saving changes", "danger")
111 else:
112 if getRedirectTarget(False):
113 return redirect('' + getRedirectTarget(True) + '')
114 return redirect('/serviceLearning/courseManagement')
116 terms = Term.select().where(Term.year >= g.current_term.year)
117 courseData = None
118 return render_template('serviceLearning/slcNewProposal.html',
119 terms = terms,
120 courseData = courseData,
121 redirectTarget = getRedirectTarget(True))
123@serviceLearning_bp.route('/serviceLearning/approveCourse', methods=['POST'])
124def approveCourse():
125 """
126 This function updates and approves a Service-Learning Course when using the
127 approve button.
128 return: empty string because AJAX needs to receive something
129 """
131 try:
132 # We are only approving, and not updating
133 if len(request.form) == 1:
134 course = Course.get_by_id(request.form['courseID'])
136 # We have data and need to update the course first
137 else:
138 course = updateCourse(request.form.copy())
140 course.status = CourseStatus.APPROVED
141 course.save()
142 flash("Course approved!", "success")
144 except Exception as e:
145 print(e)
146 flash("Course not approved!", "danger")
147 return ""
148@serviceLearning_bp.route('/serviceLearning/unapproveCourse', methods=['POST'])
149def unapproveCourse():
150 """
151 This function updates and unapproves a Service-Learning Course when using the
152 unapprove button.
153 return: empty string because AJAX needs to receive something
154 """
156 try:
157 if len(request.form) == 1:
158 course = Course.get_by_id(request.form['courseID'])
159 else:
160 course = updateCourse(request.form.copy())
162 course.status = CourseStatus.SUBMITTED
163 course.save()
164 flash("Course unapproved!", "success")
166 except Exception as e:
167 print(e)
168 flash("Course was not unapproved!", "danger")
170 return ""
172@serviceLearning_bp.route('/updateInstructorPhone', methods=['POST'])
173def updateInstructorPhone():
174 instructorData = request.get_json()
175 (User.update(phoneNumber=instructorData[1])
176 .where(User.username == instructorData[0])).execute()
177 return "success"
179@serviceLearning_bp.route('/serviceLearning/withdraw/<courseID>', methods = ['POST'])
180def withdrawCourse(courseID):
181 try:
182 if g.current_user.isAdmin or g.current_user.isFaculty:
183 withdrawProposal(courseID)
184 flash("Course successfully withdrawn", 'success')
185 else:
186 flash("Unauthorized to perform this action", 'warning')
187 except Exception as e:
188 print(e)
189 flash("Withdrawal Unsuccessful", 'warning')
190 return ""
192@serviceLearning_bp.route('/serviceLearning/renew/<courseID>/<termID>/', methods = ['POST'])
193def renewCourse(courseID, termID):
194 """
195 This function checks to see if the user is a CELTS admin or is
196 an instructor of a course (faculty) and allows courses to be renewed.
197 :return: empty string because AJAX needs to receive something
198 """
199 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID)
200 courseInstructors = [instructor.user for instructor in instructors]
201 try:
202 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors:
203 renewedProposal = renewProposal(courseID, termID)
204 flash("Course successfully renewed", 'success')
205 return str(renewedProposal.id)
206 else:
207 flash("Unauthorized to perform this action", 'warning')
208 except Exception as e:
209 print(e)
210 flash("Renewal Unsuccessful", 'warning')
212 return "", 500
214@serviceLearning_bp.route('/serviceLearning/print/<courseID>', methods=['GET'])
215def printCourse(courseID):
216 """
217 This function will print a PDF of an SLC proposal.
218 """
219 instructors = CourseInstructor.select().where(CourseInstructor.course==courseID)
220 courseInstructors = [instructor.user for instructor in instructors]
221 isCreator = Course.select().where(Course.createdBy == g.current_user, Course.id==courseID).exists()
222 if g.current_user.isCeltsAdmin or g.current_user in courseInstructors or isCreator:
223 try:
224 course = Course.get_by_id(courseID)
225 pdfCourse = Course.select().where(Course.id == courseID)
226 pdfInstructor = CourseInstructor.select().where(CourseInstructor.course == courseID)
227 pdfQuestions = (CourseQuestion.select().where(CourseQuestion.course == course))
228 questionanswers = [question.questionContent for question in pdfQuestions]
230 return render_template('serviceLearning/slcFormPrint.html',
231 course = course,
232 pdfCourse = pdfCourse,
233 pdfInstructor = pdfInstructor,
234 pdfQuestions = pdfQuestions,
235 questionanswers=questionanswers
236 )
237 except Exception as e:
238 flash("An error was encountered when printing, please try again.", 'warning')
239 print(e)
240 return "", 500
241 else:
242 abort(403)
244@serviceLearning_bp.route("/uploadCourseFile", methods=['GET', "POST"])
245def uploadCourseFile():
246 try:
247 attachment = getFilesFromRequest(request)
248 courseID = request.form["courseID"]
249 addFile= FileHandler(attachment, courseId=courseID)
250 addFile.saveFiles()
251 except:
252 flash("No file selected.", "warning")
253 return redirect('/serviceLearning/editProposal/upload/'+courseID)
256@serviceLearning_bp.route("/deleteCourseFile", methods=["POST"])
257def deleteCourseFile():
258 fileData= request.form
259 courseFile=FileHandler(courseId=fileData["courseId"])
260 courseFile.deleteFile(fileData["fileId"])
261 return ""
263@serviceLearning_bp.route('/serviceLearning/downloadApprovedCourses/<termID>', methods = ['GET'])
264def downloadApprovedCourses(termID):
265 """
266 This function allows the download of csv file
267 """
268 try:
269 designator = "downloadApprovedCourses"
270 csvInfo = approvedCourses(termID)
271 fileFormat = {"headers":["Course Name", "Course Number", "Faculty", "Term", "Previously Approved Course?"]}
272 filePath = safe_join(os.getcwd(), app.config['files']['base_path'])
273 newFile = fileMaker(designator, csvInfo, "CSV", fileFormat)
274 return send_from_directory(filePath, 'ApprovedCourses.csv', as_attachment=True)
276 except Exception as e:
277 print(e)
278 return ""