Source code for uw.local.teaching.webui.ta.eval

"""GRAD TA Evluation UI

Implements the Grad TA evaluation process online
"""

from itertools import groupby
from ll.xist.ns import html
from operator import attrgetter

from uw.local import termtools
from uw.local.dbtools import person_delegate
from uw.local.util.format import format_person

from uw.web.wsgi import status
from uw.web.wsgi.delegate import delegate_action, delegate_get_post
from uw.web.wsgi.form import use_form_param
from uw.web.wsgi.function import return_html

from uw.web.html.form import render_checkbox, render_radio, render_select, render_hidden
from uw.web.html.format import format_return, make_table_format, format_datetime

from ....util.identity import use_remote_identity

from ..delegate import taeval_delegate
from ..ui import check_mark, nullif

from .admin import render_admin_job_details

[docs]def render_ta_eval (cursor, taeval, editable, confidential=True): '''Renders TA evaluation form :param cursor: DB connection cursor. :param taeval: A databse row representing a TA evaluation. :param bool editable: Whether the evaluation is editable. :return: an html list containing a view or editable TA evaluation. ''' result = [] rating_categories = cursor.execute_tuples ("select * from ta_rating_eval_plus where eval_id = %(eval_id)s order by rating_order desc", eval_id=taeval.eval_id) ratings = ({'rating_description': 'Excellent', 'rating': 5}, {'rating_description': 'Good', 'rating': 4}, {'rating_description': 'Satisfactory', 'rating': 3}, {'rating_description': 'Unsatisfactory', 'rating': 2}, {'rating_description': 'Insufficient Opportunity to Observe', 'rating': 1}) ta_eval_history = cursor.execute_tuples ("select * from ta_eval_history where eval_id = %(eval_id)s order by update_time desc", eval_id=taeval.eval_id) if ta_eval_history and confidential: result.append (html.table ( html.tr ( html.th ('Updated on'), html.th ('By') ), (html.tr ( html.td (format_datetime (hist.update_time)), html.td (format_person (cursor, hist.update_person_id)) ) for hist in ta_eval_history) )) result.append (html.table (html.tr (html.th ("Rating Category", style="text-align: left;width: 25em"), (html.th (rating['rating_description'], style="width: 10em;") for rating in ratings)), (html.tr (html.td (rating_category.rating_description), (html.td (html.span ( render_radio (rating_category.rating_code, checked=cursor.check_eval_rating (rating=rating['rating'], eval_id=taeval.eval_id, rating_code=rating_category.rating_code), value=rating['rating'], fixed=not editable), ' ' + str(rating['rating']), style="height: 2.5em;text-align: center", class_="uw-ofs" if rating['rating'] == 2 and rating_category.rating_order == 0 else None, **{'data-name': "OVERALL"} )) for rating in ratings )) for rating_category in rating_categories))) result.append (html.p ('Please provide constructive feedback for the TA:')) result.append (html.textarea (taeval.feedback, name='feedback', rows=10, cols=100) if editable else html.p (html.i (taeval.feedback))) if confidential: result.append (html.p ('Please provide comments for the graduate chair. This information is confidential and will be shared only with the graduate chair.')) result.append (html.p ('You have indicated an Unsatisfactory rating. Please provide some explanation in the comments for the graduate chair below.', class_="alert alert-warning uw-ofs-OVERALL-2")) result.append (html.textarea (taeval.remarks, name='remarks', rows=10, cols=100) if editable else html.p (html.i (taeval.remarks))) result.append (html.p ( html.label ('Would you like to recommend this TA for a teaching assistant award? '), render_checkbox ('award', checked=taeval.award, fixed=not editable), **{'class': 'uw-ofs', 'data-name': "award"} )) result.append (html.p ('You have indicated that you would like to nominate for a teaching assistant award. Please fill out an explanation in the comments for the graduate chair above.', class_="alert alert-warning uw-ofs-award-")) return result
@return_html def taeval_get_handler (cursor, term, admin, taeval, roles): '''Get handler for TA evaluations :param cursor: DB connection cursor. :param term: Object representing a UW term. :param admin: A database row representing an admin unit. :param taeval: A database row representing a TA evaluation. :param roles: A list of user roles for a particular admin unit. :return: an html result that displays a TA evaluation with the ability to view or edit the evaluation. ''' if not {'ISC', 'INST', 'ISA'} & roles: raise status.HTTPForbidden () result = [format_return ('Main Menu', None, None, 'Offering', None, 'TA Evaluations')] ta = cursor.execute_optional_tuple ("select * from person_person where person_id = %(person_id)s", person_id=taeval.person_id) approved = cursor.eval_approved (unit_code=taeval.unit_code, term_id=term.code (), admin_id=admin.admin_id) result.append (html.p ('Please rate the performance of the %s by clicking on the appropriate buttons. Ignore any categories which are not applicable to your course.' % taeval.job_description)) result.append (html.p ('In-person communication of TA evaluations is required when the outcomes have potentially negative impacts on students such as an unsatisfactory rating to be delivered to them.')) result.append (html.p (html.b ('Teaching assistant administrators and personnel designated to assign TA units will be authorized to view all confidential information.'), html.br (), html.b ('The %s will be able to view the ratings and feedback of the evaluation.' % taeval.job_description))) result.append (html.p ('Please submit this form by clicking the submit button. When all forms for this course are complete, they must be approved by the course coordinator in order to become visible to the students.')) result.append (html.form ( render_ta_eval (cursor, taeval, editable=not approved), html.p (html.input (type="submit", name='!submit', value='Submit') if not approved else None), method="post", action="" )) return '%s (%s) %s Performance Evaluation for %s, %s' % (admin.admin_description, term.description (), taeval.job_description, ta.surname, ta.givennames) , result @use_remote_identity @use_form_param @return_html def taeval_post_handler (cursor, remote_identity, term, admin, taeval, form, roles): '''Post Handler for TA evaluations :param cursor: DB connection cursor. :param term: Object representing a UW term. :param admin: A database row representing an admin unit. :param taeval: A database row representing a TA evaluation. :param form: Contains information about the TA evaluation. :param roles: A list of user roles for a particular admin unit. :return: redirects the user to the TA evaluation list and updates changes made to the TA evaluation. ''' if not {'ISC', 'INST', 'ISA'} & roles: raise status.HTTPForbidden () if '!submit' in form: weeks, hours = form.optional_field_value('weeks'), form.optional_field_value('hours') feedback = form.optional_field_value ('feedback') remarks = form.optional_field_value ('remarks') award = form.optional_field_value ('award') is not None cursor.update_taeval (weeks=nullif(weeks), hours=nullif(hours), feedback=nullif(feedback.strip()), remarks=nullif(remarks.strip()), award=award, eval_id=taeval.eval_id) cursor.update_eval_history (eval_id=taeval.eval_id, person_id=remote_identity.person_id) cursor.execute_none ("delete from ta_rating_eval where eval_id = %(eval_id)s", eval_id=taeval.eval_id) for rating_code in cursor.execute_values ("select rating_code from ta_rating_eval_plus where eval_id = %(eval_id)s", eval_id=taeval.eval_id): rating = form.optional_field_value (rating_code) if rating is not None: cursor.execute_none ("insert into ta_rating_eval values (%(eval_id)s, %(rating_code)s, %(rating)s)", eval_id=taeval.eval_id, rating_code=rating_code, rating=rating) raise status.HTTPFound ("../") ta_eval_handler = delegate_get_post (taeval_get_handler, taeval_post_handler)
[docs]def render_ta_index (cursor, term, admin, roles, prefix=""): '''Render as HTML the TA assignments for an offering. :param cursor: DB connection cursor. :param term: Object representing a UW term. :param admin: A database row representing an admin unit. :param roles: A list of user roles for a particular admin unit. :param prefix: The URL prefix to use for links to TA evaluations. :return: An HTML fragment representing the list of TA assignments. ''' result = [] units = cursor.execute_tuples ("select ttu.*, unit_description from ta_term_unit_plus ttu natural join uw_unit natural join (select unit_code, term_id from ta_position_term_relevant_plus where (term_id, admin_id) = (%(term_id)s, %(admin_id)s) group by term_id, unit_code) tpt", term_id=term.code (), admin_id=admin.admin_id) for unit in units: ta_jobs = (render_admin_job_details (cursor, unit, term, admin, ems_roles=roles, display_prefix=prefix)) if ta_jobs is None: continue result.append (ta_jobs) if 'ISC' in roles: result.append ((check_mark, ' indicates a completed TA evaluation.', html.br(), 'TA evaluations are considered complete if all rating categories are selected and remarks are provided when necessary.')) if cursor.eval_approved (unit_code=unit.unit_code, term_id=term.code (), admin_id=admin.admin_id): result.append (html.p ("To further edit evaluations, click the checkbox below then click unapprove", html.br (), "WARNING: must re-approve after making changes for the Best TA Award.")) name, value = "!unapprove", "Unapprove!" else: result.append (html.p ("In order for a TA to be considered for the teaching assistant award, TA evaluations must be approved before the due date.", class_="alert alert-warning")) name, value = "!approve", "Approve!" result.append (html.form (html.p ( render_hidden ("unit_code", unit.unit_code), render_checkbox ("approve_check"), ' ', html.input (type="submit", name=name, value=value), ), method="post", action=prefix )) return result
@return_html def ta_eval_index_get_handler (cursor, term, admin, roles): '''Handler for viewing list of TAs for a course :param cursor: DB connection cursor. :param term: Object representing a UW term. :param admin: A database row representing an admin unit. :param roles: A list of user roles for a particular admin unit. ''' result = [format_return ('Main Menu', None, None, 'Offering', None)] result.append (render_ta_index (cursor, term, admin, roles)) return "%s (%s) TA Evaluations" % (admin.admin_description, term.description ()), result @use_form_param @use_remote_identity @return_html def ta_eval_index_post_handler (cursor, remote_identity, term, admin, roles, form): '''Handler for actions relating to TA evaluations. :param cursor: DB connection cursor. :param term: Object representing a UW term. :param admin: A database row representing an admin unit. :param roles: A list of user roles for a particular admin unit. ''' unit_code = form.required_field_value ('unit_code') if '!approve' in form and 'approve_check' in form: if not 'ISC' in roles: raise status.HTTPForbidden () cursor.execute_none ("insert into ta_term_unit_admin values (%(unit_code)s, %(term_id)s, %(admin_id)s, %(person_id)s, now())", unit_code=unit_code, term_id=term.code (), admin_id=admin.admin_id, person_id=remote_identity.person_id) elif '!unapprove' in form and 'approve_check' in form: if not 'ISC' in roles: raise status.HTTPForbidden () cursor.execute_none ("delete from ta_term_unit_admin where (unit_code, term_id, admin_id) = (%(unit_code)s, %(term_id)s, %(admin_id)s)", unit_code=unit_code, term_id=term.code (), admin_id=admin.admin_id) raise status.HTTPFound ("") ta_eval_index_handler = delegate_get_post (ta_eval_index_get_handler, ta_eval_index_post_handler) @return_html def ta_eval_view_handler (cursor, term, taeval, **params): '''Handler for viewing TA evaluations :param cursor: DB connection cursor. :param term: Object representing a uw term. :param taeval: A database row representing a TA evaluation. :return: an html result that displays the TA evluation. This handler varies from ta_eval_get_handler in that it doesn't display the editable version of the TA evaluation. Intended use is within TA admin section. ''' if 'person' in params: result = [format_return ('Term', 'Student List', 'Student Details')] person = params['person'] else: result = [format_return ('Term', 'Evaluations List')] person = cursor.execute_optional_tuple ("select * from person_identity_complete where person_id = %(person_id)s", person_id=taeval.person_id) admin = cursor.execute_optional_tuple ("select * from teaching_admin where admin_id = %(admin_id)s", admin_id=taeval.admin_id) result.append (render_ta_eval (cursor, taeval, editable=False)) return '%s (%s) %s Performance Evaluation for %s, %s' % (admin.admin_description, term.description (), taeval.job_description, person.surname, person.givennames) , result offering_taeval_handler = delegate_action (None, { 'eval': taeval_delegate (ta_eval_index_handler, ta_eval_handler), })