Page Source

from utils.display import Display, Arguments, Database, Modal
from utils.controls import *
from utils.output import *
from utils.web_exc import WebError
from utils import shapes, perms, shapes, actions
import queries, debugging
from config import docroot
import string, os
from mx import DateTime

VIDEO_FORMATS = ['mov', 'itunes_video']
AUDIO_FORMATS = ['mp3', 'itunes_audio']

class PeopleControl(SingleControl):
    """Output a comma seperated links to each instructors homepage"""
    def __init__(self):
        self.title = "People"
        self.field = "people"
        self.multi = 1
        q = queries.Select(tables="people",
                columns={ 'login' : 'login' ,
                    'name' : "concat(fname,' ',mname,' ',lname)"},
                where='retired=0',
                order=['lname'])
        q.execute()
        self.people_list = q.fetchall()


    def input_form(self,display,form_fields):
        if display.req.form_data.has_key(self.field):
            if type(display.req.form_data[self.field]) == types.StringType and self.multi:
                form_fields[self.field] = [ display.req.form_data[self.field] ]
            else:
                form_fields[self.field] = display.req.form_data[self.field]

        for p in self.people_list:
            p_org = p['login']+"_org"
            form_fields[p_org] = display.req.form_data[p_org]


    def output_disp(self,display,container):
        """All the people are in display.people, as a list of dictionaries. Each dictionary has
        fullname, login"""
        ans = []
        for dict in display.people:
            if dict['org'] == None:
                dict['org'] = ""
            else:
                dict['org'] = ", " + dict['org']
            ans = ans + ['%(fullname)s%(org)s' % dict]
        container.append(string.join(ans,"; "))

    def output_form(self,display,container):
        tr = output.TR()
        tr.append('<b>' + self.title + ':</b>')
        s = """<div class="people"><table class="people"><thead><tr><th>Person</th><th>Organization</th></tr></thead><tbody>\n""" 
        checkbox_checked = ""
        org_value = ""
        for person in self.people_list:
            for dp in display.people:
                if person['login'] == dp['login']:
                    checkbox_checked = 'checked="checked"'
                    if dp['org'] != None:
                        org_value = dp['org']
                    break
            s=s+"""<tr>\n <td class="people">"""
            s=s+"""\n  <input type="checkbox" %s """ % checkbox_checked
            s=s+"""name="people" value="%(login)s" />\n  <span class="person">%(name)s</span>\n\n </td>\n <td class="people">\n  <input class="people" type="text" name="%(login)s_org" """ % person
            s=s+"""value="%s" />""" % org_value
            s=s+"""\n </td>\n</tr>\n"""
            checkbox_checked = ""
            org_value = ""
        s = s+"""</tbody></table></div>"""

        tr.append(output.TD(attrs={'colspan' : 2}, sub=s))
        container.append(tr)

class RecordedEventTable(TABLE):
  def __init__(self):
      TABLE.__init__(self,attrs={'width':'100%'})

class RecordedEventsControl(MultipleControl):
   """Represent a Recorded Event in the list of Recorded Events.
   """
   def output_disp(self, display, nest_container):
     if display.req.login and perms.may(display.req.login, "delete", "videos"):
       display.fields['delete_button'] = ("""[&nbsp;<a href="%(action:)s&delete=""" % display.req.urls)
       display.fields['delete_button'] += ("""%(recorded_event_id)s">Delete</a>&nbsp;]""" % display.fields)
     else:
       display.fields['delete_button'] = ""

     ans = []
     for dict in display.people:
         if dict['org'] == None:
             dict['org'] = ""
         else:
            dict['org'] = ", " + dict['org']
         ans = ans + ['%(fullname)s%(org)s' % dict]

     if display.fields['screengrab_small_url'] == '':
         display.fields['screengrab_small_url'] = '/i/fill.png'

     if display.fields['event_date'] != None:
         t = display.fields['event_date'].tuple()
         display.fields['event_date'] = time.strftime("%B %e, %Y", t)

     nest_container.append("""<tr><td>""")
     nest_container.append("""<div class="video">""")
     nest_container.append("""<span class="screengrab">""")
     nest_container.append("""<a href="%(script)s/""" % display.req.urls)
     nest_container.append("""%(recorded_event_id)s">""" % display.fields)
     nest_container.append("""<img alt="Screenshot" class="screengrab-small" src="%(screengrab_small_url)s"/></a></span>""" % display.fields)
     nest_container.append(""" <div class="video-info"> """)
     nest_container.append(""" <div class="video-title"><a href="%(script)s/""" % display.req.urls)
     nest_container.append("""%(recorded_event_id)s">%(title)s</a></div>""" % display.fields)
     nest_container.append("""<div class="video-people">""")
     nest_container.append(string.join(ans,"; "))
     nest_container.append("""</div><div>""")
     if display.fields['series'] != '':
         nest_container.append("""<span class="video-series">%(series)s, </span>""" % display.fields)
     nest_container.append("""<span>%(event_date)s</span>""" % display.fields)
     nest_container.append("""</div></div> """)
     nest_container.append("""</div>""" % display.fields)
     nest_container.append("""%(delete_button)s""" % display.fields)
     nest_container.append("""</td></tr>""")
   output_form = output_disp

class RecordedEventTitleControl(TextFieldControl):
    def output_disp(self, display, nest_container):
        nest_container.append("""<div class="video-title">%(title)s</div>""" % display.fields)

class RecordedEventSeriesControl(TextFieldControl):
    def output_disp(self, display, nest_container):
        if display.fields['series'] != '':
            nest_container.append("""<span>%(series)s</span>""" % display.fields)

class RecordedEventsDateControl(TextFieldControl, DateControl):
    def output_disp(self,display,container):
        if display.fields['event_date'] != None:
            t = display.fields['event_date'].tuple()
            display.fields['event_date'] = time.strftime("%B %e, %Y", t)
            if display.fields['series'] != '':
                container.append(", ")
            container.append("""<span>%(event_date)s</span>""" % display.fields)

    def output_form(self,display,container):
        if display.fields['event_date'] != None:
            t = display.fields['event_date'].tuple()
            display.fields['event_date'] = time.strftime("%Y-%m-%d", t)
        DateControl.output_form(self,display,container)


class RecordedEventScreengrabSmallControl(TextFieldControl):
    def output_disp(self, display, nest_container):
        pass

class RecordedEventScreengrabLargeControl(TextFieldControl):
    def output_disp(self, display, nest_container):
        if display.fields['screengrab_large_url'] == '':
            display.fields['screengrab_large_url'] = '/i/fill.png'
        nest_container.append("""<span class="screengrab"><img alt="Screenshot" class="screengrab-large" src="%(screengrab_large_url)s"/></span>""" % display.fields)

class RecordedEventInfoSummaryControl(TextAreaControl):
    def output_disp(self, display, nest_container):
        nest_container.append("""<div class="summary">%(info_summary)s</div>""" % display.fields)

class RecordedEventDeepLinkQTControl(TextFieldControl):
    def output_disp(self,display,nest_container):
        for dict in display.recordings:
            if dict['format'] == "mov":
                nest_container.append("""<span class="deeplink"><a class="deeplink" href="%(url)s">QuickTime</a></span>""" % dict)
    
    def output_form(self, display, nest_container):
        for dict in display.recordings:
            if dict['format'] == "mov":
                display.fields['deep_link_mov'] = dict['url']
        TextFieldControl.output_form(self, display, nest_container)

class RecordedEventDeepLinkMP3Control(TextFieldControl):
    def output_disp(self,display,nest_container):
        for dict in display.recordings:
            if dict['format'] == "mp3":
                nest_container.append("""<span class="deeplink"><a class="deeplink" href="%(url)s">mp3</a></span>""" % dict)
    
    def output_form(self, display, nest_container):
        for dict in display.recordings:
            if dict['format'] == "mp3":
                display.fields['deep_link_mp3'] = dict['url']
        TextFieldControl.output_form(self, display, nest_container)
 
class RecordedEventDeepLinkITunesvideoControl(TextFieldControl):
    def output_disp(self,display,nest_container):
        for dict in display.recordings:
            if dict['format'] == "itunes_video":
                nest_container.append("""<span class="deeplink"><a class="deeplink" href="%(url)s">iTunes&nbsp;video</a></span>""" % dict)
    
    def output_form(self, display, nest_container):
        for dict in display.recordings:
            if dict['format'] == "itunes_video":
                display.fields['deep_link_itunes_video'] = dict['url']
        TextFieldControl.output_form(self, display, nest_container)

class RecordedEventDeepLinkITunesaudioControl(TextFieldControl):
    def output_disp(self,display,nest_container):
        for dict in display.recordings:
            if dict['format'] == "itunes_audio":
                nest_container.append("""<span class="deeplink"><a class="deeplink" href="%(url)s">iTunes&nbsp;audio</a></span>""" % dict)
    
    def output_form(self, display, nest_container):
        for dict in display.recordings:
            if dict['format'] == "itunes_audio":
                display.fields['deep_link_itunes_audio'] = dict['url']
        TextFieldControl.output_form(self, display, nest_container)

class DeeplinksStartControl(TextControl):
    def output_form(self,display,container):
        pass

    def output_disp(self,display,container):
        if len(display.recordings) > 0:
            f = "<div class=\"separator\">listen: "
            for dict in display.recordings:
                if dict['format'] in VIDEO_FORMATS:
                    f = "<div class=\"separator\">watch: "
                    break
            container.append("<div class=\"deeplinks\">%s" % f)

class DeeplinksEndControl(TextControl):
    def output_form(self,display,container):
        pass

    def output_disp(self,display,container):
        if len(display.recordings) > 0:
            container.append("</div></div>")

class DeeplinksSeparatorControl(TextControl):
    def output_form(self,display,contaimer):
        pass

    def output_disp(self,display,container):
        vcount = 0
        acount = 0
        sep = ""
        for dict in display.recordings:
            if dict['format'] in VIDEO_FORMATS:
                vcount = vcount+1
            elif dict['format'] in AUDIO_FORMATS:
                acount = acount+1
            if acount > 0 and vcount > 0:
                sep = "</div><div class=\"separator\">listen: "
                break
        container.append("%s" % sep)


class RecordedEventDisplay(Display, Database, Arguments, Modal):
  def __init__(self, req):
    Display.__init__(self, req)
    self.id = None

  def get_multiple_title(self):
    return "Videos"

  multiple_container_control = SimpleContainerControl(NestContainer, Container, RecordedEventTable)
  multiple_row_container_control = NullContainerControl()
  multiple_controls = [ RecordedEventsControl() ]

  def get_single_title(self):
    return self.fields['title']

  single_controls = [
      "<div class=\"video-single\">",
      RecordedEventScreengrabLargeControl("screengrab_large_url", title="Screengrab large", size=60), 
      RecordedEventScreengrabSmallControl("screengrab_small_url", title="Screengrab small", size=60), 
      "<div class=\"video-info-single\">",
      RecordedEventTitleControl("title", title="Title", size=60), 
      DeeplinksStartControl(),
      RecordedEventDeepLinkQTControl("deep_link_mov", title="Deep Link QuickTime", size=35),
      RecordedEventDeepLinkITunesvideoControl("deep_link_itunes_video", title="Deep Link iTunes Video", size=35),
      DeeplinksSeparatorControl(),
      RecordedEventDeepLinkMP3Control("deep_link_mp3", title="Deep Link MP3", size=35),
      RecordedEventDeepLinkITunesaudioControl("deep_link_itunes_audio", title="Deep Link iTunes Audio", size=35),
      DeeplinksEndControl(),
      PeopleControl(),
      "<div>",
      RecordedEventSeriesControl("series", title="Series", size=60), 
      RecordedEventsDateControl("event_date", title="Event Date", size=35),
      "</div>",
      "</div>",
      RecordedEventInfoSummaryControl("info_summary", title="Information Summary",rows=10),
      "</div>",
    ]

  def perform_action(self):
    # Check permission first
    # This action can either be a DB action or a deletion of a row.
    if self.req.url.internal.has_key('delete'):
      if not self.permit_action('delete'):
        raise WebError("Permission Denied",
                       """You do not have permission to
                         delete a video.""")
      # Delete a row
      delete_id = int(self.req.url.internal['delete'][0])
      self.db_delete_row(delete_id)

    elif self.get_id_argument() == 'add':
      if not self.permit_action('add'):
        raise WebError("Permission Denied",
                       """You do not have permission to
                       add a video.""")
      self.perform_database_insert()
      # go to the new video.
      return "%(script)s/%(!id)s" % self.req.urls({'id' : self.id})
    else:
      if not self.permit_mode('edit'):
        raise WebError("Permission Denied",
                       """You do not have permission to
                       edit this video.""")

      self.perform_database_update()
      # display this data now
      return self.req.urls['mode:display']

  def make_page(self, page):
    self.prep_database()
    page.set_type("info")
    self.shape = shapes.DISP

    if self.is_add():
      self.mode = 'edit'

    # if logged in, show the possibities.
    if self.req.login:
      if self.permit_action('add'):
        page.add_navigation("%(script)s/add" % self.req.urls, "Add a Recorded Event")
      if self.id != 'all' and self.id != None:
        page.add_navigation("%(script)s/all" % self.req.urls, "All Recorded Events")

    if self.is_multiple():
      page.set_title(self.get_multiple_title())
      page.append("""<h1>%s</h1>""" % self.get_multiple_title())
      page.append(self.multiple_database())
    else:
      if self.get_mode() == 'edit' or self.is_add():
        self.shape = shapes.FORM
      page.set_title(self.get_single_title())
      if self.is_add():
        page.append("<h1>Add a Recorded Event</h1>")
      else:
        self.add_modes_to_page(page) # Don't need modes in multiple or add
      page.append(self.single_database())

  def permit_mode(self, mode):
    return ((mode == 'display') or
            (mode == 'edit' and
             perms.may(self.req.login, 'edit', 'videos')))

  def permit_action(self, action):
    return ((action == 'add' and
             perms.may(self.req.login, 'add', 'videos')) or
            (action == 'delete' and
             perms.may(self.req.login, 'delete', 'videos')))

  def get_id_argument(self):
    if self.id: return self.id
    if self.req.url.arguments:
      arg = self.req.url.arguments[0]
      # handle some special cases
      if arg in ('add', 'all'):
        self.id = arg
      else:
        try:
          self.id = int(arg)
        except (ValueError, TypeError):
          pass
    return self.id

  def is_multiple(self):
    return not self.get_id_argument() or self.get_id_argument() == 'all'

  def is_add(self):
    return (self.get_id_argument() and
            self.get_id_argument() == 'add' and
            self.permit_action('add'))

  def db_rows(self):
    return self.query.count()

  def db_query(self):
    id = self.get_id_argument()

    # if this is an add, there's no querying to do.
    if self.is_add():
        return

    q = queries.Select(tables="recorded_events",
            columns={ "title" : "title",
                "series" : "series",
                "screengrab_small_url" : "screengrab_small_url",
                "screengrab_large_url" : "screengrab_large_url",
                "info_summary" : "info_summary",
                "event_date" : "event_date",
                "recorded_event_id" : "id"
                },
            order="event_date DESC"
            )
    if id != 'all' and id is not None:
        q.where="""recorded_events.id=%s""" % queries.represent_value(id)
    q.execute()
    if q.count() == 0 and not self.is_multiple():
        raise WebError("Recorded Event Not Found",
                     """The indicated Recorded Event does not exist in this database.""")
    self.query = q

  def db_fetch(self):
    id = self.get_id_argument()
    # If we're adding, return some defaults
    if self.is_add():
      self.fields = { 
          "title" : "",
          "info_summary" : "",
          "series" : "",
          "event_date" : DateTime.now(),
          "screengrab_small_url" : "",
          "screengrab_large_url" : "",
          }
      self.people = [{"login" : '', "fullname" : '', "org" : ''}]
      self.recordings = [{"url" : '', "format" : ''}]
      for f in VIDEO_FORMATS+AUDIO_FORMATS:
          self.fields['deep_link_%s' % f] = ""
    else:
      # otherwise actually do the fetch.
      self.fields = self.query.fetch()
      if self.fields is not None:
          recorded_event_id = self.fields['recorded_event_id']
          ptables=["people","recorded_events_login"]
          pcolumns={ "fullname" : "concat(fname,' ',mname,' ',lname)",
                  "login": "people.login",
                  "org" : "organization"}
          pwc="people.login = recorded_events_login.login and recorded_events_login.recorded_event_id = %d" % recorded_event_id
          p = queries.Select(tables=ptables, columns=pcolumns, where=pwc)
          p.execute()
          self.people = p.fetchall()
          rtables=["recorded_events","recordings"]
          rcolumns={ "url" : "url",
                  "format" : "format"}
          rwc = "recorded_events.id = recordings.recorded_event_id and recorded_events.id = %d" % recorded_event_id
          r = queries.Select(tables=rtables, columns=rcolumns, where=rwc)
          r.execute()
          self.recordings = r.fetchall()
          for f in VIDEO_FORMATS+AUDIO_FORMATS:
              self.fields['deep_link_%s' % f] = ""

    return self.fields

  def get_row_from_fields(self):
    # Gather the data into a database row
    row = {}
    for field in ("title","series", "info_summary", "event_date", "screengrab_small_url","screengrab_large_url"):
      row[field] = self.form_fields[field]
    if row['title'] == '': 
        raise WebError("Must provide a title")
    return row

  def db_people(self,id):
    if not self.form_fields.has_key('people'):
        return
    d = queries.Delete(table="recorded_events_login",
            where="recorded_event_id=%d" % id)
    d.execute()
    self.people = self.form_fields['people']
    rows = []
    for person in self.people:
        org = self.form_fields['%s_org' % person]
        if org != '':
            rows.append({'login' : person, 'recorded_event_id' : id, 'organization' : org})
        else:
            rows.append({'login' : person, 'recorded_event_id' : id})

    ins = queries.Insert(table="recorded_events_login", rows=rows)
    ins.execute()

  def db_recordings(self,id):
      urls = []
      count = 0
      for f in VIDEO_FORMATS+AUDIO_FORMATS:
          dl = "deep_link_%s" % f
          u = self.form_fields[dl]
          if u != '':
              count = count+1
          if u != '' and u not in urls:
              urls.append(u)
      if len(urls) != count:
          raise WebError("You need to provide distinct deep links.")
      for f in VIDEO_FORMATS+AUDIO_FORMATS:
          dl = "deep_link_%s" % f
          d = queries.Delete(table="recordings",
                  where="recorded_event_id=%d and format=\"%s\"" % (id,f))
          d.execute()
          if self.form_fields[dl] != '':
              row = [{ "recorded_event_id" : id,
                      "url" : self.form_fields[dl],
                      "format" : f }]
              ins = queries.Insert(table="recordings", rows=row)
              ins.execute()
    
  def db_update(self):
    id = self.get_id_argument()
    row = self.get_row_from_fields()
    u = queries.Update(table="recorded_events",
                       where="id = %d" % id,
                       sets=row)
    u.execute()
    self.db_people(id=id)
    self.db_recordings(id=id)
    actions.notify('videos',
                             """\
User '%s' changed this recorded event as follows:

%s
""" % (self.req.login, self.represent_row(row)))

  def represent_row(self, row):
    # Represent a row (as a dictionary) in a manner suitable for
    # emailing
    return """
Title: %s
Series: %s
Information Summary: %s
Screengrab small URL: %s
Screengrab large URL: %s
""" % (row['title'], row['series'], row['info_summary'],
       row['screengrab_small_url'], row['screengrab_large_url'])

  def db_insert(self):
    row = self.get_row_from_fields()
    i = queries.Insert(table="recorded_events",
                       rows=[row])
    i.execute()
    # mark this down for later.  See self.perform_action().
    self.id = i.insert_id()
    self.db_people(self.id)
    self.db_recordings(self.id)
    actions.notify('videos',
                             """\
User '%s' added the following row to the recorded events table:

%s
""" % (self.req.login, self.represent_row(row)))

  def represent_row(self, row):
    # Represent a row (as a dictionary) in a manner suitable for
    # emailing
    return """
Title: %s
Series: %s
Information Summary: %s
Screengrab small URL: %s
Screengrab large URL: %s
""" % (row['title'], row['series'], row['info_summary'],
       row['screengrab_small_url'], row['screengrab_large_url'])

  def db_delete_row(self, id):
    s = queries.Select(tables="recorded_events",
                       where="id = %d" % id)
    s.execute()
    row = s.fetch()
    if row:
      actions.notify('videos',
                               """\
User '%s' deleted the following row from the recorded events table:

%s
""" % (self.req.login, self.represent_row(row)))
      d = queries.Delete(table="recorded_events",
                         where="id = %d" % id)
      d.execute()
      f = queries.Delete(table="recorded_events_login",
              where="recorded_event_id=%d" % id)
      f.execute()
      g = queries.Delete(table="recordings",
              where="recorded_event_id=%d" % id)
      g.execute()

def new(req):
  return RecordedEventDisplay(req)