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

"""UI-related utility routines.

These are mostly functions to generate fragments of HTML.  Typically they are
here because they were factored out of a different part of the system, but
are not considered worthy of being moved to an application-independent place
in the package tree.
"""

from datetime import date, datetime
from operator import attrgetter

from ll.xist.ns import html

from uw.web.html.form import render_hidden
from uw.web.html.format import make_table_format, format_datetime
from uw.web.html.join import html_join

from uw.local.util.format import format_person

[docs]def format_date_helpful (value): if value in [None, datetime.max, date.max]: return None return value.strftime ('%Y-%m-%d (%A, %B %-d)')
[docs]def format_duration (duration, none=None): """Format a duration. :param duration: duration (datetime.timedelta) or None :param none: value to use if the input is None :return: if duration is none, return param none or None, else return duration in a convenient form. The duration is assumed to be less than a day, and only the hours and minutes are included """ if duration is None: return none return ':'.join (str (duration).split (':')[:2])
[docs]def format_seating (seating): """Format a seating designation. :param seating: seating designation as a boolean (True for Assigned) :return: 'Assigned' or 'Not Assigned' as appropriate depending on the provided seating designation. Returns None if the input is None :rtype: str or None """ if seating is None: return None return 'Assigned' if seating else 'Not Assigned'
[docs]def format_independent (independent): """Format an examination independence choice. :param independent: boolean indicating if a sitting is "exams independent" :return: 'Exams Independent' or 'Exams Together' as appropriate depending on the provided independence choice. Returns None if the input is None :rtype: str or None """ if independent is None: return None return 'Exams Independent' if independent else 'Exams Together'
[docs]def combine_column_fields (columns): """Combine the fields from the specified set of table column definitions. :param columns: iterable of column specifications represented as 3-tuples :return: forms the union of the third elements (field names) of the columns. Any set of field names which is None is skipped (i.e., treated as the empty set) Possibly this really belongs in uw.web.html.format. """ result = set () for _, _, fields in columns: if fields is not None: result.update (fields) return result
[docs]class AttrDict (dict): """A sub-class of dict which also makes the values available as attributes. This is a convenience class that allows d.a to mean the same thing as d['a'] if d is an instance of this class. This may be used to make objects which look much like database row results (result fields available as attributes) but which have values computed within Python. """ def __getattr__ (self, name): try: return self[name] except KeyError as e: raise AttributeError (e)
[docs]def render_columns_as_rows (row, columns): """Render a database row as a two-column table. :param row: a database row :param columns: some column specifications represented as 3-tuples :return: renders the database row as a table with one row per column. The first column of the table is the column headings while the second column is the field values. The columns to display are determined by the specified set of columns as used by uw.web.html.format.make_table_format :rtype: HTML table <table> """ return html.table ( html.tr ( html.th (title + ':'), html.td (valuegetter (row)) ) for valuegetter, title, _ in columns )
[docs]def format_allocated_count (allocated, reserved_d, undesignated): """Format counts of allocated seats/candidates. :param allocated: the total allocated items :param reserved_d: the number of reserved items :param undesignated: the number of undesignated items :return: the number of allocated items, followed in parentheses by the number of reserved and undesignated items, suppressing as much as possible in the event some of the numbers in parentheses are zero :rtype: str or list """ result = '%s' % allocated parens = html_join ([ '%s undesignated' % undesignated if undesignated else None, '%s reserved' % reserved_d if reserved_d else None ], sep='; ') if parens is None: return result else: return [result, ' (', parens, ')']
[docs]def format_candidate_list (cursor, candidates, extra_columns=[]): """Format a list of examination candidates. :param cursor: DB connection cursor :param candidates: iterable of candidates :param extra_columns: additional columns to include, represented as 3-tuples :return: an HTML table with one row per candidate and several standard columns, as well as any additional columns specified :rtype: HTML table <table> """ return make_table_format ( ('UW ID', attrgetter ('uw_id')), ('Candidate', lambda r: [render_hidden ("c", r.person_id), format_person (cursor, r.person_id)]), ('Start Time', lambda r: format_datetime (r.start_time)), ('With', attrgetter ('sitting_admin_description')), ('Extra?', lambda r: ' ✓' if r.extra_candidate else None), ('Reserved?', lambda r: ' ✓' if r.candidate_reserved else None), ('Seating', lambda r: format_seating (r.candidate_assigned)), ('Seat', lambda r: ('Unseated' if r.candidate_assigned else None) if r.seat_code is None else '%s %s %s' % (r.building_code, r.room_code, r.seat_code)), *extra_columns ) (candidates)
[docs]def format_sections_multiline (sections): """Re-format formatted section descriptions onto multiple lines. :param str sections: The result of off_instruct_section_format() or similar. :return: The same section descriptions, with spaces replaced by hard spaces and semicolons replaced by <br> elements. :rtype: str This function puts each course on a separate line and forces each course to stay on a single line. """ if sections is None: return None else: return html_join (sections.replace (' ', ' ').split ('; '), sep=html.br ())
[docs]def nullif (value, none=''): """Return the given value, or None if it is blank. :param value: the value :param none: if value is the same as this, return None :return: None if value and none are the same, otherwise the value Utility routine for converting blanks (or specified value) to None for HTML generation. """ if value == none: return None else: return value
[docs]def bool_to_yes_no (value): """Convert boolean to string. :param value: the value :return: 'Yes' if the value is equivalent to True, and 'No' otherwise :rtype: str """ return "Yes" if value else "No"
[docs]def render_tooltip (title=''): """Render a tooltip with a given title. :param title: the message to display in the tooltip :return: an icon that when hovered will display a tooltip message :rtype: HTML span <span> """ return html.span (class_="odyssey-tooltip fa fa-question-circle-o", title=title)
check_mark = html.div ({"aria-labelledby": "Checkmark…"}, class_="checkmark", role="img")