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

"""Room Editor UI pages

This currently consists of only the note editor, includes handlers
for editing, deleting, and updating room notes. Will also include
the room editor which allows the user to edit room maps
"""

import psycopg2, json

from ll.xist.ns import html, specials

from uw.web.html.form import render_select, render_checkbox
from uw.web.html.format import format_email, format_return

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

from .delegate import room_delegate

[docs]def note_instructions (cursor, room): """Displays the description and instructions for the room_note :param cursor: DB connection cursor :param room: A database row representing a room :return: a list of html elements to be added to the page :rtype: list """ result = [html.p ("This description will be displayed in the exam schedule portal \ to provide instructions on how to locate the room.")] room_note = cursor.execute_optional_value ("select room_note from room_room where room_id = %(room_id)s", room_id=room.room_id) if not room_note: result.append (html.p ("There is currently no room note.")) else: result.append (html.p ("Current room note: " + specials.literal (room_note))) return result
[docs]def note_section (cursor, room): """Displays the note editor section :param cursor: DB connection cursor :param room: A database row representing a room :return: a list of html elements to be added to the note editor page including the instructions, the CKEditor, and form buttons :rtype: list """ result = [(html.h2 ("Room Note"))] result.append (note_instructions (cursor, room)) result.append (html.p ("To edit the room note, enter the text below then click Update")) result.append (html.textarea (room.room_note, name="room_note", id="room_note", rows=5, cols=40)) result.append (html.script ("CKEDITOR.replace ('room_note', \ {language: 'en', \ toolbar: [{ name: 'document', items : [ 'Source'] }, \ { name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] }, \ { name: 'editing', items : ['SpellChecker'] },{ name: 'basicstyles', items : [ 'Bold','Italic','Underline','Strike'] }, \ { name: 'paragraph', items : [ 'NumberedList','BulletedList','-','Outdent','Indent','-'] }, \ { name: 'links', items : [ 'Link','Unlink'] }, \ { name: 'insert', items : ['Image'] }, \ { name: 'styles',items : [ 'Styles','Format'] }, \ { name: 'tools',items : [ 'Maximize', 'About' ]}]})", type="text/javascript")) result.append (html.p (html.input (type="submit", name='!update_note', value="Update"), html.input (type="submit", name='!delete_note', value="Delete"))) return result
@return_html def note_edit_get_handler (cursor, room, form, global_roles): """Note editor GET URL handler. :param cursor: DB connection cursor :param room: A database row representing a room :param form: the form results :return: tuple of (building code and room code, html elements to be added to the note editor page) :rtype: (str, list) Displays the current room note and CKEditor text area, includes form controls for updating the room note to the CKEditor input and deleting the room note. """ result = [html.p ("Return to ", html.a ("Room Index", href="../../../../../room/"), ", ", html.a ("Room Information-%s %s" % (room.building_code, room.room_code), href="../../../../id/%s/" % room.room_id))] result.append (html.form (note_section (cursor, room), method='post', action='')) return '%s %s Note Editor' % (room.building_code, room.room_code), result @return_html def note_edit_post_handler (cursor, room, form, global_roles): """Note editor POST URL handler. :param cursor: DB connection cursor :param room: A database row representing a room :param form: the form results Implements actions based on form results. These can be one of: - Deletes current room note from the room - Updates current room note If an error occurs, the error message is shown to the user. """ if '!update_note' in form: room_note = form.optional_field_value ('room_note') if not room_note: room_note = None if '!delete_note' in form: room_note = None try: cursor.execute_none ("update room_room set room_note = %(room_note)s where room_id = %(room_id)s", room_note=room_note, room_id=room.room_id) except psycopg2.Error as error: return 'Please Go Back', [html.p ("Invalid Room Note please enter a valid XML fragment."), 'Please contact ', format_email ('odyssey@uwaterloo.ca'), ' for more assistance.', html.p ("The following error message occured:"), html.p (error.pgerror)] raise status.HTTPFound ("../../../../id/%s/" % room.room_id) note_edit_handler = delegate_get_post (note_edit_get_handler, note_edit_post_handler) @return_html def room_edit_get_handler (cursor, room, form, global_roles): """Room map editor GET URL handler. :param cursor: DB connection cursor :param room: A database row representing a room :param form: the form results :return: tuple of (building and room code, room map editor) :rtype: (str, list) Displays a form for editing the room map with live display of what the room map will look like. """ result = [format_return ('Main Menu', 'Room Index', None, None)] if room.room_effective is not None: raise status.HTTPForbidden () form = [] form.append (html.table ( html.tr ( html.th ('Room Width:'), html.td (html.input (type="number", name="room-width", class_="room-seating-input", value=room.room_width, onkeypress="return event.charCode >= 48", min="1", required="")), ), html.tr ( html.th ('Room Depth:'), html.td (html.input (type="number", name="room-depth", class_="room-seating-input", value=room.room_depth, onkeypress="return event.charCode >= 48", min="1", required="")), ), )) seat_types = cursor.execute_tuples ("select seat_type_code, seat_type_description from room_seat_type") seat_types.append(("NO SEAT", "No Seat")) form.append (html.div ( render_checkbox ("s", class_="seat-checkbox-template"), html.span ('Change selected seats: '), render_select ('', ((code, '%s - %s' % (code, label)) for code, label in seat_types), value="TBL", class_="seat-type-selector"), html.p (html.input (type="button", value="Update Selected Seats", class_="seat-type-update-selected")), )) form.append (html.div (class_="room-seats-editor")) form.append (html.p ('Note: left/right arrows are for creating aisles between seats. A red border between two seats indicates an aisle between them.')) form.append (html.input (type="hidden", name="room-seat-json", value=json.dumps (cursor.execute_tuples ("select * from room_seat where room_id = %(room_id)s", room_id=room.room_id)))) form.append (html.input (type="hidden", name="room-aisle-json", value=json.dumps (cursor.execute_tuples ("select * from room_row_aisle where room_id = %(room_id)s", room_id=room.room_id)))) form.append (html.p (html.input (type="submit", value="Submit", class_="create-room-button"))) result.append (html.form (form, class_="create-room-form", action="")) result.append (html.p (class_="room-editor-error text-error")) return 'Room Editor—%s %s' % (room.building_code, room.room_code), result @return_json def room_edit_post_handler (cursor, room, form, global_roles): """Room map editor POST URL handler. :param cursor: DB connection cursor :param room: A database row representing a room :param form: the form results :return: JSON object of room id :rtype: str Implements the room map designed in the GET handler. """ # Cheap hack to get around deleting the proper seats and aisles cursor.callproc_none ("room_edit_resize", room.room_id, 0, 0) # Resize to new room size room_width = form.required_field_value ('room-width') room_depth = form.required_field_value ('room-depth') cursor.callproc_none ("room_edit_resize", room.room_id, room_width, room_depth) # Add new set of seats seats = form.multiple_field_value ('seats') for seat in seats: seat_row, seat_col, seat_type_code = seat.split('-') cursor.callproc_none ("room_edit_seat", room.room_id, seat_col, seat_row, seat_type_code) # Add new set of aisles aisles = form.multiple_field_value ('aisles') for aisle in aisles: seat_col_left, seat_col_right, seat_row = aisle.split('-') cursor.callproc_none ("room_edit_aisle", room.room_id, seat_col_left, seat_col_right, seat_row, True) json_reply = json.dumps ({'id': room.room_id}) return json_reply room_edit_handler = delegate_get_post (room_edit_get_handler, room_edit_post_handler) room_edit_handler = delegate_action (None, { 'id': room_delegate (None, delegate_action (room_edit_handler, { 'note': note_edit_handler,})), })