# This file is part of ReportTool # ReportTool (Felicity) is copyright 2004-8 Steve Butterfill. # # ReportTool is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # ReportTool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with ReportTool. If not, see . # # If you want to use ReportTool under a difference licence, email # s.butterfill@warwick.ac.uk. from turbogears import controllers, expose from turbogears import identity, redirect, error_handler from cherrypy import request, response import logging #custom imports from model import * from datetime import datetime import turbogears from turbogears import widgets, validate, validators from sqlobject.sqlbuilder import Select, AND, CONTAINSSTRING #supporting modules import file_upload, logic, util, webhelp #functions for creating widgets etc from logic import modulegroup #default upload dir to ./uploads from elementtree import ElementTree import os import cherrypy from felicity.logic import report #other controllers from subcontrollers.asyncpages import AsyncPages from subcontrollers.componentpages import ComponentPages from subcontrollers.configpages import ConfigPages from subcontrollers.deptpages import DeptPages from subcontrollers.exportpages import ExportPages, ExportMePages from subcontrollers.feedbackpages import FeedbackPages from subcontrollers.jobpages import JobPages from subcontrollers.module_grouppages import ModuleGroupPages from subcontrollers.modulepages import ModulePages from subcontrollers.myreports import MyReports from subcontrollers.notepages import NotePages from subcontrollers.personal_tutorpages import PersonalTutorPages from subcontrollers.programmepages import ProgrammePages from subcontrollers.registerpages import RegisterPages from subcontrollers.reportpages import ReportPages from subcontrollers.staffpages import StaffPages from subcontrollers.studentpages import StudentPages from subcontrollers.tstpages import TstPages from subcontrollers.uploadpages import UploadPages log = logging.getLogger(__name__) class _ModuleAssignment(object): def __init__(self,module_id,staff_id): self.module_id=module_id self.staff_id=staff_id class Root(controllers.RootController): @expose() def testkw(self,**kw): """can send forms here to see what is being posted""" return str(kw) @expose("felicity.templates.error") def error(self, msg=""): """error page""" #TODO make more informative return dict(error_msg=msg) @expose("felicity.templates.select_module_group") @identity.require(identity.in_group("student")) def select_module_group(self, module_code): """page for students to select which module_group to join for module with the specified module_code""" module = Module.from_code(module_code) if module is None: tg.flash("No module with code %s" % module_code) tg.redirect("/") if not module.allow_module_group_change: tg.flash("Module %s is not currently allowing seminar group changes." % module_code) tg.redirect("/") available_groups = modulegroup.available_groups(module) groups_table = webhelp.tables.module_groups(show_students=False, allow_delete=False, show_signup_link=True) return dict(mod=module, available_groups=available_groups, groups_table=groups_table, term = Term.current_term(), year=Year.current_year()) @expose("felicity.templates.select_module_group") @identity.require(identity.in_group("student")) def join_module_group(self, module_group_id): """Page for students to join the specified module group""" module_group = ModuleGroup.from_id(module_group_id) if module_group is None: tg.flash("Error: no module group with id %s" % module_group_id) tg.redirect("/") module = module_group.module student = webhelp.student() #check student not already a member of a module group for this module current_mg = ModuleGroup.group_for_student(student=student, module=module) if current_mg is not None: if current_mg==module_group: tg.flash("You are already a member of group %s; you cannot sign up for the same group twice." % module_group) tg.redirect("/") else: tg.flash("You are already a member of group %s for this module; you cannot also sign up for group %s" % (current_mg, module_group)) #check module_group is not full if module_group.full: tg.flash("Sorry, you cannot sign up for group %s because it is full" % module_group) tg.redirect("/select_module_group/"+module.code) #sign student up for this group try: module_group.addStudent(student) if current_mg is not None: current_mg.removeStudent(student) tg.flash("You are now a member of group %s for %s" % (module_group, module.code)) except Exception, e: ModuleGroup._connection.rollback() tg.flash("Sorry, there was an error attempting to assign you to group %s. %s" % (module_group, e)) tg.redirect("/") @expose('felicity.templates.personal_tutor_assign') def test_students(self): return dict() @expose() def test_redirect(self): """checks redirects are working. Should forward to dept page""" turbogears.redirect("/dept") @expose(template="felicity.templates.welcome") @identity.require(identity.not_anonymous()) def index(self): """initial page for staff. If user is student, defers to index_student""" student = webhelp.student() if student is not None: #do the student welcome page return self.index_student(student) dept = webhelp.cookies.dept() staff = webhelp.staff() reports_to_write = report.modules_with_unsubmitted_reports(staff) reports_written = report.modules_with_submitted_reports(staff) #get modules staff teaching this term term = webhelp.cookies.term() year = webhelp.cookies.year() modules_teaching = ModuleLeader.modules_for_staff(staff=staff, year=year, term=term) seminar_teaching = ModuleGroup.all(staff=staff, term=term, year=year) term = webhelp.cookies.term() terms = term.all_so_far() return dict(x="", staff=staff, term=term, year=year, reports_to_write=reports_to_write, reports_written=reports_written, modules_teaching=modules_teaching, seminar_teaching=seminar_teaching, terms=terms) def index_student(self, student): #we're gonna use all_reports incl. non-submitted to work out what feeddback to give all_reports = Report.all(student=student, only_submitted=False, only_current=True) reports = [r for r in all_reports if (r.submitted is not None and r.approved is not None)] #-- feedback removed #modules = [r.module for r in all_reports] #list of modules to leave feedback on #modules_feedback_done = [f.module for f in Feedback.all(student=student, only_submitted=True, only_current=True)] #-- #have to be done in dict because template uses database lookups #my_module_groups = ModuleGroup.groups_for_student(student), #modules_to_sign_up_for = modulegroup.modules_to_sign_up_for(student), return dict(tg_template="felicity.templates.welcome_student", reports=reports, my_module_groups = ModuleGroup.groups_for_student(student), modules_to_sign_up_for = modulegroup.modules_to_sign_up_for(student), #modules = modules, #modules_feedback_done = modules_feedback_done, student = webhelp.student(), term = Term.current_term(), year=Year.current_year()) @expose(template="felicity.templates.login") def login(self, forward_url=None, previous_url=None, *args, **kw): if not identity.current.anonymous \ and identity.was_login_attempted() \ and not identity.get_identity_errors(): raise redirect(forward_url) forward_url=None previous_url= request.path if identity.was_login_attempted(): msg=_("The credentials you supplied were not correct or " "did not grant access to this resource.") elif identity.get_identity_errors(): msg=_("You must provide your credentials before accessing " "this resource.") else: msg=_("Please log in.") forward_url= request.headers.get("Referer", "/") response.status=403 return dict(message=msg, previous_url=previous_url, logging_in=True, original_parameters=request.params, forward_url=forward_url) @expose() def logout(self): if not identity.current.anonymous: identity.current.logout() raise redirect("/") #----------------- #start custom bits #subpages component = ComponentPages() config = ConfigPages() dept = DeptPages() export = ExportPages() export_me = ExportMePages() feedback = FeedbackPages() job = JobPages() module = ModulePages() module_group = ModuleGroupPages() myreports = MyReports() note = NotePages() personaltutor = PersonalTutorPages() programme = ProgrammePages() register = RegisterPages() report = ReportPages() staff = StaffPages() student = StudentPages() test = TstPages() upload = UploadPages() #helper pages async = AsyncPages() #for aboutme page user_name_field = widgets.TextField(name="user_name",label="user name", attrs=dict(disabled=True)) email_address_field = widgets.TextField(name="email_address", label="email address", validator=validators.Email(not_empty=True)) password_field = widgets.PasswordField(name="rt_password",label="password", validator=validators.All(validators.PlainText(not_empty=True), validators.MinLength(4))) #----- # controllers for the 'aboutme' page @expose(template="felicity.templates.aboutme2") @identity.require(identity.not_anonymous()) def aboutme(self, **kw): user = identity.current.user #these allow user to select a working term or year year_select = webhelp.form_parts.year_select() term_select = webhelp.form_parts.term_select() change_term_url=tg.url("/_set_term") change_year_url=tg.url("/_set_year") year_id = webhelp.cookies.year().id term_id = webhelp.cookies.term().id #form for changing user's working dept if 'config' in identity.current.groups: dept_form = webhelp.forms.dept_form dept = webhelp.cookies.dept() dept_data = { 'dept_id':dept.id } else: dept_form, dept, dept_data = None, None, None return dict(user=user, year_select=year_select, term_select=term_select, change_term_url=change_term_url, change_year_url=change_year_url, year_id=year_id, term_id=term_id, dept_form=dept_form, dept_data=dept_data ) @expose() @identity.require(identity.not_anonymous()) def aboutme_save(self, email_address, **kw): """updates users email address""" user = identity.current.user s_or_s = webhelp.staff_or_student() if s_or_s is None: tg.flash("Strange error updating your email address, please report code E#671") tg.redirect("/aboutme") try: s_or_s.email_address = email_address turbogears.flash("Update successful.") except UpdateError, e: tg.flash("Sorry, it was not possible to update your record at this time. (%s)" % str(e)) raise turbogears.redirect("/aboutme") @expose() @identity.require(identity.not_anonymous()) def aboutme_change_password(self, old_password, new_password, **kw): """updates users password""" user = identity.current.user if not user.password == old_password: tg.flash("Sorry, your old password is incorrect.") tg.redirect("/aboutme") if new_password is None or len(new_password)<6: tg.flash("Sorry, your new password must be at least 6 characters long.") tg.redirect("/aboutme") user.password = new_password tg.flash("Password changed successfully.") tg.redirect("/aboutme") @expose() @identity.require(identity.not_anonymous()) def _change_year(self, year_id): """sets the user's preferred year""" year = Year.get(year_id) #throw exception if year_id invalid webhelp.cookies.year_set(year_id) turbogears.flash("Year changed to %s" % year) raise turbogears.redirect("/aboutme#time") @expose() @identity.require(identity.not_anonymous()) def _change_term(self, term_id): """sets the user's preferred term""" term = Term.get(str(term_id)) #throw exception if term_id invalid webhelp.cookies.term_set(term_id) turbogears.flash("Term changed to %s" % term) raise turbogears.redirect("/aboutme#time") @expose() @identity.require(identity.in_group("config")) def _change_dept(self, dept_id): """Changes the users current working department. Returns to the 'my preferences' page """ #return str(dept_id) dept = Dept.get(str(dept_id)) webhelp.cookies.dept_set(dept.id) turbogears.flash("Working department changed to %s" % dept.name) raise turbogears.redirect("/aboutme#dept") #--- # simple menu pages go here @expose(template="felicity.templates.configure") @identity.require(identity.in_any_group("admin", "config")) def configure(self): dept = webhelp.cookies.dept() return dict(dept=dept)