Source code for uw.local.teaching.webui.offering

"""Offering-related UI pages.

Implements the main screen for an offering, including the form for choosing
the default seating (rush or assigned) for assessments in that offering.
"""

from ll.xist.ns import html

from uw.dbtools import copy_to_csv

from uw.web.wsgi.delegate import *
from uw.web.wsgi.form import use_form_param
from uw.web.wsgi.function import return_html, return_csv

from uw.web.html.form import render_select, render_radio
from uw.web.html.format import format_return, format_datetime, format_email, format_expandable_div, format_tabs
from uw.web.html.join import english_join

from uw.local.util.identity import use_remote_identity
from uw.local.util.format import format_person

from ..db.classlist import classlist_csv

from .accommodation import accommodation_handler, accommodation_exam_index_handler
from .administer import exam_administered_handler, exam_scheduled_handler, exam_deadline_index_handler, exam_deadline_edit_get_handler
from .aids_edit import exam_aids_editor
from .authority import format_personnel_by_user, format_personnel_by_role
from .crowdmark import crowdmark_upload_master
from .delegate import exam_delegate, sitting_delegate, room_delegate, deadline_delegate
from .admin_exams_edit import render_exam_create_form, exam_create_handler
from .candidate import candidate_edit_handler
from .division import division_handler
from .enrolment import enrol_handler
from .exam import exam_labels_handler, exam_folders_handler, exam_posting_list_handler, exam_sequence_lookup_handler, exam_lookup_handler, exam_allzip_handler, sitting_exam_index_handler, sitting_exam_handler, exam_index_handler, exam_handler, render_admin_exam_list
from .exam_scan import exam_scan_handler
from .exam_edit import exam_sitting_add_handler, exam_editor_setup_handler, exam_editor_seating_handler, exam_editor_printing_handler
from .exam_schedule import exam_schedule_handler, schedule_submission_handler
from .grades import offering_grades_handler
from .offering_conflict import offering_conflict_handler
from .offering_edit import offering_edit_handler
from .order_edit import order_edit_handler
from .personnel import personnel_handler
from .sitting import sitting_index_handler, sitting_handler, exam_sitting_index_handler, exam_sitting_handler, render_admin_sitting_list, sitting_proctor_handler
from .sitting_edit import sitting_editor_handler, sitting_add_room_handler, sitting_spare_editor_handler
from .room import sitting_room_index_handler, sitting_room_handler, exam_sitting_room_index_handler, exam_sitting_room_handler
from .special import exam_special_case_handler
from .ta.eval import offering_taeval_handler, render_ta_index
from .ui import nullif
from .upload import upload_download_pdf
from .override_uploader import override_uploader_handler

@use_form_param
@delegate_get_post
@return_csv
def offering_classlist_handler (cursor, term, admin, roles, form):
    """Classlist download URL handler.

    Generates a .csv classlist for the relevant offering. If query parameter
    'dropped' is used, it will download a classlist of withdrawn students.
    """
    result = classlist_csv (cursor, term, admin.admin_id, 'dropped' in form)

    return [result, '%s (%s) Classlist.csv' % (admin.admin_description, term.description ())]

@delegate_get_post
@return_csv
def offering_talist_handler (cursor, term, admin, roles):
    """TA list download URL handler.

    Generates a .csv TA list for the relevant offering.
    """
    result = copy_to_csv (cursor, "select surname, givennames, userid, job_code, assigned_units from ta_position_assignment natural join person_identity_complete where (term_id, admin_id) = (%d, %d) order by surname, givennames, job_code" % (term.numericCode (), admin.admin_id))

    return [result.getvalue (), '%s (%s) TA Support.csv' % (admin.admin_description, term.description ())]

[docs]def render_assessment_section (cursor, term, admin, exams, roles): result = [] # Scheduling Request Form section scheduling = cursor.execute_optional_tuple ("select * from teaching_admin_term natural left join teaching_admin_term_exam_schedule where (term_id, admin_id) = (%(term_id)s, %(admin_id)s)", term_id=term.code (), admin_id=admin.admin_id) # scheduling is None if this offering is not actually enabled; # can only reach this page by editing URL in that case. scheduling_submitted = scheduling and scheduling.scheduling_submitted is not None if 'ISC' in roles: if scheduling_submitted: result.append (html.p (html.a ('View/revise final assessment scheduling request form', href="scheduling"))) else: result.append (html.div ('Please fill out the ', html.a ('final assessment scheduling request form', href="scheduling"), ' before creating assessments.', class_="alert alert-warning")) ## Assessment section if scheduling_submitted: if 'ISC' in roles: if exams: exams.append ( html.tr ( html.td ( render_exam_create_form (cursor), colspan=21, # number of columns in table align="center", ) ) ) else: result.append (render_exam_create_form (cursor)) result.append (exams) if 'ISC' in roles: result.append (html.p (html.a ('Final Assessment Conflict Times', href="conflicts"))) return result
[docs]def format_offering_assessments (cursor, term, admin, roles): '''Format a (title, id, content) triple for the Assessments section of the offering page, to be rendered with the format_tabs function. :param cursor: DB connection cursor. :param term: In-context academic term. :param admin: In-context admin unit. :param roles: In-context user roles. :return: (Title, id, HTML content) triple for the Assessments section of the offering page. ''' content = [] # Authorization section if not 'ISC' in roles: content.append (html.h2 ('Authorization')) role_descriptions = cursor.execute_values ("select role_description from auth_role where role_code = ANY (%(roles)s)", roles=list (roles)) content.append (html.p ('You are authorized as: ', english_join (*role_descriptions), html.br (), 'To add assessments you must be authorized as an Instructional Support Coordinator.')) isc_persons = cursor.execute_tuples ("select * from auth_offering_personnel_complete where (term_id, admin_id, role_code) = (%(term_id)s, %(admin_id)s, 'ISC') and role_current and not auth_backup", term_id=term.code (), admin_id=admin.admin_id) exam_reps = cursor.execute_tuples ("select * from auth_offering_personnel_complete where (term_id, admin_id, role_code) = (%(term_id)s, %(admin_id)s, 'EXAM') and role_current and not auth_backup", term_id=term.code (), admin_id=admin.admin_id) if isc_persons: auth_persons = (format_person (cursor, isc_person.person_id) for isc_person in isc_persons) elif exam_reps: auth_persons = (format_person (cursor, exam_rep.person_id) for exam_rep in exam_reps) else: auth_persons = [format_email ('odyssey@uwaterloo.ca')] content.append (html.p ('If you need to be authorized as an Instructional Support Coordinator, please contact: ', english_join (*auth_persons), class_="alert alert-warning")) exams, count = render_admin_exam_list (cursor, term, admin, "exam/", True) if 'ISC' in roles or exams: content.append (render_assessment_section (cursor, term, admin, exams, roles)) return ("Assessments (%s)" % count, 'assessments', content)
@return_html def offering_index_get_handler (cursor, term, admin, roles): """Offering page GET URL handler. Shows information about the relevant offering. Display is different if the user has the ISC role, which is permitted to make changes. The information includes a list of assessments, a list of sittings, section enrolment, and the personnel authorized for the offering. """ result = [format_return ('Main Menu', None, None)] links = [ html.a ('Enrollment…', href="enrol"), html.a ('Personnel…', href="personnel"), ] if admin.admin_accommodation: links.append (html.a ('Accommodation…', href="accommodation/")) links.append (html.a ('Accommodation Assessment Deliveries…', href ="accommodation-exams/")) if links: result.append (html.h2 ('Quick Links')) result.append (html.ul (html.li (link) for link in links)) tab_lst = [] if admin.admin_level >= 15: tab_lst.append (format_offering_assessments (cursor, term, admin, roles)) elif admin.admin_id in [20050, 20070, 20080]: result.append (html.h2 ('Assessment Scheduling and Administration')) result.append (html.ul (html.li (html.a ('Scheduled Assessments…', href="exams-scheduled/")), html.li (html.a ('Administered Assessments…', href="exams-administered/")))) else: result.append (html.h2 ('Final Assessment Scheduling Request')) result.append (html.ul (html.li (html.a ('Scheduling request summary…', href="schedule-request/")))) sittings, count = render_admin_sitting_list (cursor, term, admin, "sitting/", True) tab_lst.append (("Sittings (%s)" % count, 'sittings', (sittings if sittings else "No sittings have been created."))) result.append (format_tabs (tab_lst)) return "%s (%s)" % (admin.admin_description, term.description ()), result offering_index_handler = delegate_get_post (offering_index_get_handler) offering_handler = delegate_action (offering_index_handler, { # Offering summary 'sitting': sitting_delegate ( sitting_index_handler, # List of sittings in offering delegate_action (sitting_handler, { # Sitting overall 'room': room_delegate ( sitting_room_index_handler, # List of rooms in sitting sitting_room_handler # Room in sitting ), 'add-room': sitting_add_room_handler, 'exam': exam_delegate ( sitting_exam_index_handler, # List of exams in sitting sitting_exam_handler # Exam in sitting ), 'edit': sitting_editor_handler, 'proctor': sitting_proctor_handler, }) ), 'exam': exam_delegate ( exam_index_handler, # List of exams in offering delegate_action (exam_handler, { # Exam overall 'sitting': sitting_delegate ( exam_sitting_index_handler, # List of sittings in exam delegate_action (exam_sitting_handler, { # Sitting in exam 'edit-spares': sitting_spare_editor_handler, 'room': room_delegate ( exam_sitting_room_index_handler, # List of rooms exam_sitting_room_handler # Room in sitting ), 'add-room': sitting_add_room_handler, 'proctor': sitting_proctor_handler, }) ), 'add-sitting': exam_sitting_add_handler, 'crowdmark-upload': crowdmark_upload_master, 'edit-aids': exam_aids_editor, 'edit-candidate': candidate_edit_handler, 'edit-order': order_edit_handler, 'edit-printing' : exam_editor_printing_handler, 'edit-scanning': exam_scan_handler, 'edit-seating' : exam_editor_seating_handler, 'edit-setup' : exam_editor_setup_handler, 'labels': exam_labels_handler, 'folders': exam_folders_handler, 'markentry': exam_lookup_handler, 'postinglist': exam_posting_list_handler, 'sequence': exam_sequence_lookup_handler, 'allzip': exam_allzip_handler, 'special': exam_special_case_handler, 'download': upload_download_pdf, 'override-uploader': override_uploader_handler, }) ), 'classlist': offering_classlist_handler, 'division': division_handler, 'enrol': delegate_file_only (enrol_handler), 'exams-administered': exam_administered_handler, 'exams-scheduled': exam_scheduled_handler, 'exams-deadline': deadline_delegate ( exam_deadline_index_handler, exam_deadline_edit_get_handler), 'grades': offering_grades_handler, 'schedule-request': schedule_submission_handler, 'scheduling': exam_schedule_handler, 'talist': offering_talist_handler, 'ta': offering_taeval_handler, 'edit': offering_edit_handler, 'exam-create': exam_create_handler, 'conflicts': offering_conflict_handler, 'personnel': personnel_handler, 'accommodation': accommodation_handler, 'accommodation-exams': accommodation_exam_index_handler, })