Page Source
from utils.display import Display, Database, FileCopy, Modal
from utils.controls import *
from utils.output import *
from utils import shapes, perms, actions
from utils.static_strings import StaticString
from utils.web_exc import WebError
import queries, debugging
from config import docroot
import string, os, shutil
class PhotoVideoControl(SingleControl):
def output_form(self,display,container):
pass
def output_disp(self,display,container):
q = queries.Select(tables=["recorded_events", "recorded_events_login"],
columns={'id' : 'id',
'screengrab_small_url' : 'screengrab_small_url',
'event_date' : 'event_date',
'title' : 'title'},
where="""
recorded_events_login.login = \"%(login)s\" AND
recorded_events_login.recorded_event_id = recorded_events.id
""" % display.fields)
q.execute()
videos = q.fetchall()
container.append("""
<div class="photovideo">
""")
if display.fields['photos']:
debugging.log("display: %s" % display.fields.keys())
if display.fields['mname'] != '':
display.fields['alt_name'] = "%(fname)s %(mname)s %(lname)s" % display.fields
else:
display.fields['alt_name'] = "%(fname)s %(lname)s" % display.fields
for photo in display.fields['photos']:
r = display.req.urls({'login' : display.fields['login'],
'fmt' : photo['format'],
'alt' : display.fields['alt_name']})
container.append("""
<div class="photo">
<img alt="%(!alt)s" src="%(native_secure:file:photos)s/%(!login)s.%(!fmt)s"/>
</div>
""" % r)
if len(videos) > 0:
container.append("""
<div class="videos">
<div class="videos-title">Videos</div>
""")
video_list = []
for v in videos:
t = v['event_date'].tuple()
v['event_date'] = time.strftime("%B %e, %Y", t)
container.append("""
<div class="video">
<div class="video-screengrab">
<a href="/videos/%(id)s">
<img alt="%(title)s)" class="video-img-screengrab" src="%(screengrab_small_url)s"/>
</a>
</div>
<div class="video-info">
<div class="video-title"><a href="/videos/%(id)s">%(title)s</a></div>
<div class="video-date">%(event_date)s</div>
</div>
</div>
""" % v)
container.append("""
</div>
""")
container.append("""
</div>
""")
class GroupAffiliationControl(SingleControl):
def output_form(self,display,container):
pass
def output_disp(self,display,container):
q = queries.Select(tables=["group_affiliation_login", "group_affiliation"],
columns={'group_affiliation_name' : 'group_affiliation_name'},
where="""
group_affiliation_login.login = "%(login)s" AND
group_affiliation_login.group_affiliation_id = group_affiliation.id
""" % display.fields)
q.execute()
groups = q.fetchall()
if len(groups) > 0:
group_list = []
for g in groups:
group_list.append(g['group_affiliation_name'])
container.append("<h2>Interests</h2>\n<blockquote>")
container.append(string.join(group_list,", "))
container.append("\n</blockquote>")
class PersonControl(MultipleControl):
"""Represent a person in the bullet-list of people. Uses the
'grouping' field and a NestContainer parent to create the titles for
different groupings of people."""
def output_disp(self, display, nest_container):
# First see if we're beginning a new grouping
if display.fields['grouping'] != display.last_grouping:
display.last_grouping = display.fields['grouping']
nest_container.append(
NestContainer.Out("""<h3>%s</h3>\n""" % display.last_grouping))
# Now just make the column normally
nest_container.append("""<a href="%(person!login)s">%(!name)s</a>"""
% display.req.urls(display.fields) )
output_form = output_disp
class MayEditPeopleControl(IfThenElseControl):
"""A little hack: titles should only be editable by people that
actually have permission (e.g., in the permission table) to edit people.
So people can't edit their own titles."""
def __init__(self, admincontrols=[], othercontrols=[]):
IfThenElseControl.__init__(self, admincontrols, othercontrols)
def condition_form(self, display):
return perms.may(display.req.login, 'edit', 'people')
class PeopleDisplay(Display, Database, Documents, FileCopy, Modal, StaticString):
def get_multiple_title(self):
return "Members of the Department of Computer Science"
multiple_container_control = SimpleContainerControl(NestContainer, Container, BulletColumns)
multiple_row_container_control = NullContainerControl()
multiple_controls = [ PersonControl() ]
def get_single_title(self):
if self.fields['mname']:
return "%s %s %s" % (self.fields['fname'],
self.fields['mname'],
self.fields['lname'])
else:
return "%s %s" % (self.fields['fname'],
self.fields['lname'])
single_controls = [
# we only display the photo here.. in the form, it appears at the bottom.
IfShapeControl(dispcontrols=PhotoVideoControl()),
"<h1>", TextFieldControl("fname", title="First Name"),
" ", TextFieldControl("mname", title="Middle Name"),
" ", TextFieldControl("lname", title="Last Name"), "</h1>",
"<blockquote>",
MayEditPeopleControl(admincontrols=
[ CommentControl("""\
Titles are used to categorize people on the main
<a href="%(sect:people)s">people page</a>. As such, it is crucial that
the titles be entered correctly. The system used to make these
categorizations is described on the
<a href="%(sect:people)s/groupings">groupings page</a>."""),
TitlesControl() ],
othercontrols=NoEditControl(None, title="Titles")),
RetiredControl(),
"</blockquote>\n",
GroupAffiliationControl(),
"<h2>Contact Information</h2>\n<blockquote>",
TextAreaControl("address", title="Address", cols=30, auto_wrap=0),
IfExistsControl("office",["<br />\nOffice: ", TextFieldControl("office", title="Office")]),
IfExistsControl("phone",["<br />\nPhone: ", TextFieldControl("phone", title="Phone")]),
IfExistsControl("fax",["<br />\nFax: ", TextFieldControl("fax", title="Fax")]),
"<br />\n", EmailControl("email", title="Email"),
"</blockquote>\n",
IfExistsControl("homepage",
[ "<h2>Personal Homepage</h2><blockquote>",
URLControl("homepage", title="Homepage"),
"</blockquote>\n" ] ),
IfExistsControl("research",
[ "<h2>Research</h2>\n<blockquote>",
TextAreaControl("research", title="Research", rows=8),
"</blockquote>\n" ] ),
IfExistsControl("education",
[ "<h2>Education</h2>\n<blockquote>",
TextAreaControl("education", title="Education", rows=8, auto_wrap=0),
"</blockquote>\n" ] ),
IfExistsControl("additional",
[ "<h2>Additional</h2>\n<blockquote>",
TextAreaControl("additional", title="Additional Info", rows=8),
"</blockquote>\n" ] ),
IfExistsControl("projects",
[ "<h2>Projects</h2>\n",
ProjectsControl() ] ),
IfExistsControl("labs",
[ "<h2>Laboratories</h2>\n",
LabsControl() ] ),
IfExistsControl("bibliographies",
[ """<h2>List of Publications</h2>\n<blockquote>Available in """,
DocumentControl(category="bibliographies", title="Bibliography"),
".</blockquote>\n" ] ),
# We want to show this control down here in the FORM shape (because it's
# really big onscreen).
IfShapeControl(formcontrols=PhotoControl(title="Photo")),
# MayEditPeopleControl(admincontrols=IfShapeControl(formcontrols=PhotoControl(title="Photo"))),
IfExistsControl("tech_reports",
[ "<h2>Technical Reports</h2>\n<blockquote>",
PersonTechreportControl(),
"</blockquote>\n" ] ),
]
####
# The two front-line functions, which get called from dispatch
#
def perform_action(self):
if self.permit_mode('edit'):
self.perform_database_update()
actions.notify('people', """\
User '%s' edited the record for person '%s'.
""" % (self.req.login, self.get_login_argument()))
else:
raise WebError("""Permission Denied""",
"""You don't have permission to edit this page""")
def make_page(self, page):
# Get some starting info from the DB
self.prep_database()
# Fix up the page
self.add_page_links(page)
# check the shape we should be in, based on the mode.
if self.get_mode() in ('edit', 'add'):
self.shape = shapes.FORM
if self.is_multiple():
# Plural page has extra decorations
page.append("<h1>%s</h1>" % self.get_multiple_title())
self.make_page_top(page)
self.last_grouping = None # PersonControl needs this
page.append(self.multiple_database())
else:
page.append(self.single_database())
def permit_mode(self, mode):
login_arg = self.get_login_argument()
return ((mode == 'display') or # display mode
(mode == 'edit' and # permitted to edit
perms.may(self.req.login,'edit','people')) or
(mode == 'edit' and # self-edit
not self.is_multiple() and
login_arg and
login_arg == self.req.login) or
(mode == 'add' and # permitted to add
perms.may(self.req.login,'add','people')))
def get_login_argument(self):
if not hasattr(self, 'login_arg'):
if self.req.url.arguments:
self.login_arg = self.req.url.arguments[0]
# Legacy URL support
if self.req.url.internal.has_key('person'):
self.login_arg = self.req.url.internal.get('person')[0]
if self.req.url.internal.has_key('login'):
self.login_arg = self.req.url.internal.get('login')[0]
else:
# No argument
self.login_arg = None
return self.login_arg
####
# db_query and db_fetch -- get info
#
def db_query(self):
if self.is_multiple():
q = queries.Select(tables=['people', 'titles', 'groupings', 'grouping_priorities'],
columns = { 'name' : queries.SQL('concat(fname, " ", lname)'),
'login' : 'people.login',
'grouping' : 'grouping_priorities.name' },
where="""\
people.login = titles.login and
(titles.title like groupings.title or groupings.title is NULL) and
(titles.context like groupings.context or groupings.context is NULL) and
groupings.id = grouping_priorities.id and
not people.retired and not people.pseudo""",
order=['grouping_priorities.priority', 'lname', 'fname', 'mname'],
distinct=1)
else:
# Single query
login = self.get_login_argument()
q = queries.Select(tables=['people'],
where="""\
people.login = %s and not people.pseudo""" % queries.represent_value(login) )
q.execute()
if q.count() == 0:
raise WebError("Person Not Found", "The specified person has no record on this website.")
self.query = q
def is_multiple(self):
if self.req.url.arguments:
return None
return 1
def db_rows(self):
return self.query.count()
def db_fetch_titles(self, login):
q = queries.Select(tables="titles",
where="login = %s" % queries.represent_value(login),
order="priority")
q.execute()
titles = []
for d in q.fetchall():
titles.append((d['title'], d['context'], d['priority']))
self.fields['titles'] = titles
def db_fetch_projects(self, login):
q = queries.Select(tables=("projects", "project_members"),
where="""login = %s and
projects.project_id = project_members.project_id"""
% queries.represent_value(login),
columns={'name' : 'projects.project_title',
'id' : 'projects.project_id' },
order="projects.project_title")
q.execute()
projects = []
for d in q.fetchall():
projects.append((d['name'], d['id']))
self.fields['projects'] = projects
def db_fetch_labs(self, login):
q = queries.Select(tables=("labs", "lab_members"),
where="""login = %s and
labs.lab_id = lab_members.lab_id""" % queries.represent_value(login),
columns={'name' : 'labs.lab_name',
'id' : 'labs.lab_id' },
order="labs.lab_name")
q.execute()
labs = []
for d in q.fetchall():
labs.append((d['name'], d['id']))
self.fields['labs'] = labs
def db_fetch_tech_reports(self, login):
# We select one row for each author of each tech report that this person
# has authored. Ex:
# TR-26-82 'The foo of bar' .. .. Dustin Mitchell
# TR-26-82 'The foo of bar' .. .. Virna Gupta
# TR-27-16 'The bar of baz' .. .. Brendan Strejcek
# TR-27-16 'The bar of baz' .. .. Dustin Mitchell
q = queries.Select(tables=("tech_reports as reports",
"tech_report_authors as authors",
"""tech_report_authors as author left join people as sponsors
on reports.sponsor = sponsors.login"""),
where="""author.login = %s and
author.rep_id = reports.rep_id and
reports.rep_id = authors.rep_id and
reports.obsolete != 1"""
% queries.represent_value(login),
columns={'title' : 'reports.title',
'obsolete' : 'reports.obsolete',
'rep_id' : 'reports.rep_id',
'foobar' : 'if(LOCATE("-",reports.rep_id,4) = 6,INSERT(reports.rep_id,4,0,"19"),reports.rep_id)',
'sponsor' : 'concat(sponsors.fname, " ", sponsors.lname)',
'pub_date' : 'date_format(reports.pub_date, "%e %M, %Y")',
'a_login' : 'authors.login',
'a_name' : 'authors.name',
'a_prio' : 'authors.priority' },
order="foobar desc")
q.execute()
trs = []
last_rep_id = None
for d in q.fetchall():
# If this begins a new techreport...
if last_rep_id != d['rep_id']:
# Insert a new record, with this single author in it
last_rep_id = d['rep_id']
trs.append( { 'title' : d['title'],
'rep_id' : d['rep_id'],
'pub_date' : d['pub_date'],
'sponsor' : d['sponsor'],
'authors' : [ ( d['a_login'], d['a_name'], d['a_prio'] ) ] } )
else:
# Append this author to the last-added techreport
trs[-1]['authors'].append( ( d['a_login'], d['a_name'], d['a_prio'] ) )
self.fields['tech_reports'] = trs
def db_fetch(self):
self.fields = self.query.fetch()
if not self.is_multiple():
login = self.fields['login']
self.db_fetch_titles(login)
self.db_fetch_projects(login)
self.db_fetch_labs(login)
self.db_fetch_documents('bibliographies', login)
self.db_fetch_documents('photos', login)
self.db_fetch_tech_reports(login)
return self.fields
####
# db_update -- make changes
#
def db_update_titles(self, login):
# We lock down the titles table, delete everything for this person,
# then re-add those we've received in self.form_fields.
# self.form_fields['titles'] is a dictionary from
# priority-number to (title, context).
# Lock the table, so it doesn't change between select & insert.
lock = queries.Lock(tables="titles", locktype="WRITE")
lock.lock()
try:
# Delete all of the old rows for this user
d = queries.Delete(table='titles',
where='login = %s' % queries.represent_value(login))
d.execute()
# make a list of new rows that should be inserted
rows = []
for priority, tc in self.form_fields['titles'].items():
title, context = tc
if title or context:
rows.append({'login' : login,
'priority' : priority,
'title' : title,
'context' : context})
# And now insert the rows
if rows:
i = queries.Insert(table='titles', rows=rows)
i.execute()
finally:
lock.unlock()
def db_update_membership(self, table, id_column_name, field, login):
# We lock down the given table, delete everything for this person,
# then re-add those we've received in self.form_fields.
# self.form_fields[field] is a list of ("%ss" % id_column_name).
# Lock the table, so it doesn't change between select & insert.
lock = queries.Lock(tables=table, locktype="WRITE")
lock.lock()
try:
# Delete all of the old rows for this user
d = queries.Delete(table=table,
where='login = %s' % queries.represent_value(login))
d.execute()
# make a list of new rows that should be inserted
rows = []
for id in self.form_fields[field]:
rows.append({'login' : login,
id_column_name : id})
# And now insert the rows
if rows:
i = queries.Insert(table=table, rows=rows)
i.execute()
finally:
lock.unlock()
def db_update_projects(self, login):
self.db_update_membership('project_members', 'project_id', 'projects', login)
def db_update_labs(self, login):
self.db_update_membership('lab_members', 'lab_id', 'labs', login)
def db_update(self):
login = self.get_login_argument()
form_fields = self.form_fields
# First take care of the simple fields
u = queries.Update(table="people", where="login = %s" % queries.represent_value(login))
for field in ('fname', 'mname', 'lname', 'address', 'office',
'phone', 'fax', 'email', 'homepage', 'research',
'education', 'additional', 'retired'):
u[field] = form_fields[field]
u.execute()
# More of the little hack:
if perms.may(self.req.login, 'edit', 'people'):
self.db_update_titles(login)
self.db_update_projects(login)
self.db_update_labs(login)
self.db_update_documents('bibliographies', login)
self.db_update_documents('photos', login)
#####
# Utility functions
def add_page_links(self, page):
# Prep the page: page type, navigation, etc.
page.set_type("people")
page.set_title("Department Members")
self.add_modes_to_page(page)
# Multiple:
if self.is_multiple():
# Everyone logged in should get this link.
if self.req.login:
page.add_navigation('%(sect:people)s/groupings' % self.req.urls, 'Groupings')
page.add_navigation('%(sect:people)s/alphabetical' % self.req.urls, 'Alphabetical')
# Single:
else:
page.set_title('%s %s %s' % (self.fields['fname'],
self.fields['mname'],
self.fields['lname']))
page.add_navigation('%(sect:people)s' % self.req.urls, 'People')
# Only those who can add people should get this link.
if self.permit_mode('add'):
page.add_navigation('%(sect:people)s/add' % self.req.urls, 'Add Person')
def make_page_top(self, page):
if self.get_mode() == 'edit':
page.append("""The grouping of people by category on this page is
controlled from the <a href="%(sect:people)s/groupings">groupings
page</a>.""" % self.req.urls)
else:
page.append(self.GetString(key="whoswho",display=self,title_fn=page.set_title))
def new(req):
return PeopleDisplay(req)