[open-ils-commits] r939 - in servres/trunk/conifer: . integration integration/linktool integration/linktool/templates syrup (gfawcett)

svn at svn.open-ils.org svn at svn.open-ils.org
Tue Jul 27 23:17:51 EDT 2010


Author: gfawcett
Date: 2010-07-27 23:17:48 -0400 (Tue, 27 Jul 2010)
New Revision: 939

Added:
   servres/trunk/conifer/integration/clew-memberships
   servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml
Modified:
   servres/trunk/conifer/integration/clew-sections-for-site
   servres/trunk/conifer/integration/linktool/app.py
   servres/trunk/conifer/integration/linktool/templates/associate.xhtml
   servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml
   servres/trunk/conifer/integration/uwindsor.py
   servres/trunk/conifer/syrup/models.py
   servres/trunk/conifer/urls.py
Log:
sakai (linktool) integration almost done...

Added: servres/trunk/conifer/integration/clew-memberships
===================================================================
--- servres/trunk/conifer/integration/clew-memberships	                        (rev 0)
+++ servres/trunk/conifer/integration/clew-memberships	2010-07-28 03:17:48 UTC (rev 939)
@@ -0,0 +1,53 @@
+#!/usr/local/bin/python-oracle-cgi-wrapper
+# -*- mode: python -*-
+
+import os
+import cgi
+import cx_Oracle
+import simplejson
+import re
+
+CONN_STRING = '***/***@********'
+conn = cx_Oracle.connect(CONN_STRING)
+#import cgitb; cgitb.enable(display=True)
+
+def memberships(uid):
+    q = ("select realm_id, role_name, S.title, DBMS_LOB.SUBSTR(P.value, 64) "
+         "from sakai_realm_rl_gr G "
+         "left join sakai_realm R on G.realm_key = R.realm_key "
+         "left join sakai_user_id_map M on G.user_id=M.user_id "
+	 "left join sakai_site S on S.site_id = substr(R.realm_id, 7) "
+         "left join sakai_realm_role RR on G.role_key = RR.role_key "
+	 "left join sakai_site_property P on P.site_id = S.site_id and P.name='term_code' "
+         "where eid=:1 and active=1 "
+         "and regexp_like(realm_id, '^/site/.{36}$') ")
+    cursor = conn.cursor()
+    cursor.execute(q, (uid,))
+    coursepat = re.compile(r'^(\d\d-\d\d-\d\d\d)')
+    for realm, role, title, term in cursor.fetchall():
+        site = realm[6:]
+        tmp = coursepat.match(title)
+        course = tmp and tmp.group(1) or None
+        # term: convert 'W08+S08' to ['2008W', '2008S']
+        try:
+            terms = ['20%s%s' % (t[-2:], t[0]) for t in term.split('+')]
+        except:
+            terms = []
+        yield {'site': site, 'role': role, 'title': title, 'terms': terms, 
+               'course': course}
+
+form = cgi.FieldStorage()
+uid  = form['uid'].value
+compress = 'deflate' in os.environ.get('HTTP_ACCEPT_ENCODING', '')
+resp = simplejson.dumps(list(memberships(uid)))
+
+print 'Status: 200 OK'
+print 'Content-Type: application/json'
+if compress:
+    import zlib
+    print 'Content-Encoding: deflate'
+    print
+    print zlib.compress(resp)
+else:
+    print
+    print resp

Modified: servres/trunk/conifer/integration/clew-sections-for-site
===================================================================
--- servres/trunk/conifer/integration/clew-sections-for-site	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/integration/clew-sections-for-site	2010-07-28 03:17:48 UTC (rev 939)
@@ -1,18 +1,14 @@
-#!/Users/graham/bin/python-oracle-cgi-wrapper
+#!/usr/local/bin/python-oracle-cgi-wrapper
 # -*- mode: python -*-
 
 import os
 import cx_Oracle
-import re
-import sys
-import warnings
 import simplejson as json
-import time
 import cgitb
-
 #cgitb.enable(display=True)
 
-conn = cx_Oracle.connect('sakai/PASSWORD at clew')
+CONN_STRING = '***/***@********'
+conn = cx_Oracle.connect(CONN_STRING)
 
 try:
     siteid = os.environ['PATH_INFO'][1:]

Modified: servres/trunk/conifer/integration/linktool/app.py
===================================================================
--- servres/trunk/conifer/integration/linktool/app.py	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/integration/linktool/app.py	2010-07-28 03:17:48 UTC (rev 939)
@@ -1,5 +1,6 @@
 from conifer.here                    import HERE
 from conifer.plumbing.genshi_support import TemplateSet
+from datetime                        import date, timedelta
 from django.http                     import (HttpResponse, HttpResponseRedirect,
                                              HttpResponseNotFound,
                                              HttpResponseForbidden)
@@ -13,40 +14,87 @@
                 {'models': models, '_': _})
 
 
-def linktool_welcome(request, command=u''):
+def linktool_welcome(request):
     user = authenticate(request=request)
     if user is None:
         return HttpResponseForbidden('You are not allowed here.')
     else:
         login(request, user)
+        _role   = request.GET['role']
+        extrole = request.session['clew-role'] = callhook('decode_role', _role) or _role
         extsite = request.session['clew-site'] = request.GET['site']
-        extrole = request.session['clew-role'] = request.GET['role']
+
         related_sites = list(models.Site.objects.filter(group__external_id=extsite))
         if len(related_sites) == 1:
-            return HttpResponse("<html><head/><body onload=\"top.location='%ssite/%s/';\">"
-                                "Redirecting..."
-                                "</body></html>" % (
-                    request.META['SCRIPT_NAME'] or '/',
-                    related_sites[0].id))
+            site_url = related_sites[0].site_url()
+            html     = ("<html><head/><body onload=\"top.location='%s';\">"
+                        "Redirecting..."
+                        "</body></html>") % site_url
+            return HttpResponse(html)
         elif len(related_sites):
             return g.render('whichsite.xhtml', **locals())
-        elif extrole == 'Instructor':
-            # This isn't quite right yet. I want to give the instructor a
-            # chance to associate with an existing unassociated site in the
-            # same term as the Sakai site. I don't want them to associate with
-            # a site that's in an older Term, but should give them the change
-            # to copy/reuse an old site. Or, they can make a brand-new Site if
-            # they want. 
-
-            # This reminds me that it should be a warning to edit an old site
-            # (one in a past Term). Otherwise, profs will add items to old
-            # sites, and think they are actually ordering stuff.
-
-            possibles = models.Site.taught_by(user)
-            if possibles:
-                return g.render('associate.xhtml', **locals())
-            else:
-                return g.render('create_new.xhtml', **locals())
+        elif extrole == 'INSTR':
+            # TODO: This reminds me that it should be a warning to
+            # edit an old site (one in a past Term). Otherwise, profs
+            # will add items to old sites, and think they are actually
+            # ordering stuff.
+            today     = date.today()
+            possibles = list(models.Site.taught_by(user))
+            current   = [s for s in possibles if s.term.midpoint() >= today]
+            ancient   = [s for s in possibles if s.term.midpoint() < today]
+            return g.render('associate.xhtml', **locals())
         else:
+            # TODO: implement me
             return g.render('choose_dest.xhtml', **locals())
 
+
+def linktool_new_site(request):
+    extsite = request.session['clew-site']
+    extrole = request.session['clew-role']
+    assert extrole == 'INSTR'
+    assert request.user.can_create_sites(), \
+        'Sorry, but you are not allowed to create sites.'
+    extgroups  = callhook('external_memberships', request.user.username)
+    extsite    = [d for d in extgroups if d['group'] == extsite][0]
+    coursecode = extsite['course']
+    termcode   = extsite['terms'][0]
+    try:
+        course = models.Course.objects.get(code=coursecode)
+        term   = models.Term.objects.get(code=termcode)
+    except:
+        # note, this doesn't have to be an exception. I could provide
+        # them with a form to specify the correct course and term
+        # codes. But for now, we bail.
+        return g.render('new_site_cannot.xhtml', **locals())
+    site = models.Site.objects.create(
+        course = course,
+        term   = term,
+        owner  = request.user,
+        service_desk = models.ServiceDesk.default())
+    group = models.Group.objects.create(
+        site        = site,
+        external_id = extsite)
+    models.Membership.objects.create(
+        group = group, 
+        user  = request.user, 
+        role  = 'INSTR')
+    return HttpResponseRedirect(site.site_url())
+
+def linktool_associate(request):
+    site = models.Site.objects.get(pk=request.GET['site'])
+    assert site in request.user.sites(role='INSTR'), \
+        'Not an instructor on this site! Cannot copy.'
+    assert request.user.can_create_sites(), \
+        'Sorry, but you are not allowed to create sites.'
+    today = date.today()
+    assert site.term.midpoint() >= today, \
+        'Sorry, but you cannot associate to such an old site.'
+    return HttpResponse('associate: not implemented yet')
+
+def linktool_copy_old(request):
+    site = models.Site.objects.get(pk=request.GET['site'])
+    assert site in request.user.sites(role='INSTR'), \
+        'Not an instructor on this site! Cannot copy.'
+    assert request.user.can_create_sites(), \
+        'Sorry, but you are not allowed to create sites.'
+    return HttpResponse('copy old: not implemented yet')

Modified: servres/trunk/conifer/integration/linktool/templates/associate.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/associate.xhtml	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/integration/linktool/templates/associate.xhtml	2010-07-28 03:17:48 UTC (rev 939)
@@ -2,17 +2,39 @@
       xmlns:xi="http://www.w3.org/2001/XInclude"
       xmlns:py="http://genshi.edgewall.org/">
   <xi:include href="linktoolmaster.xhtml"/>
-  <head/>
+  <head>
+    <style type="text/css">
+      	li { margin-top: 0.5em; }
+    </style>
+  </head>
   <body>
-    <h1 style="padding-top: 1em;">Associate?</h1>
+    <h1>No associated reserves list.</h1>
     <p>There is currently no set of reserves materials associated with
     this site. As an instructor in this site, you can choose one of
     the following options:</p>
-    <h2>todo: finish this...</h2>
-    <ul>
-      <li py:for="site in possibles">
-	${site}
+    <ol>
+      <li>
+	<div><b>Link to one of my current reserves list</b></div>
+	<ul>
+	  <li py:if="not current">None available</li>
+	  <li py:for="site in current">
+	    <a href="associate?site=${site.id}">${site}</a>
+	  </li>
+	</ul>
       </li>
-    </ul>
+      <li>
+	<div><b>Copy a reserves list I've used in the past</b></div>
+	<ul>
+	  <li py:if="not ancient">None available</li>
+	  <li py:for="site in ancient">
+	    <a href="copy_old?site=${site.id}">${site}</a>
+	  </li>
+	</ul>
+      </li>
+      <li>
+	<div><b><a href="new_site">Create a new reserves list for this site</a></b></div>
+      </li>
+    </ol>
+
   </body>
 </html>

Modified: servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/integration/linktool/templates/linktoolmaster.xhtml	2010-07-28 03:17:48 UTC (rev 939)
@@ -10,6 +10,10 @@
     <head py:attrs="select('@*')">
       ${select('*')}
       <base target="_top"/>
+      <style type="text/css">
+	div#outer { width: inherit; max-width: 960px; }
+	h1 { padding-top: 1em; }
+      </style>
     </head>
   </py:match>
 </html>

Added: servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml
===================================================================
--- servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml	                        (rev 0)
+++ servres/trunk/conifer/integration/linktool/templates/new_site_cannot.xhtml	2010-07-28 03:17:48 UTC (rev 939)
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      xmlns:py="http://genshi.edgewall.org/">
+  <xi:include href="linktoolmaster.xhtml"/>
+  <head>
+    <title>testing</title>
+    <script type="text/javascript"
+	    py:if="False">
+      window.onload = function() { top.location='${request.META['SCRIPT_NAME'] or '/'}'; };
+    </script>
+  </head>
+  <body>
+    <h1>Cannot create site...</h1>
+    <p>Sorry, but your site's course code (${coursecode or 'unknown'})
+    and/or term code (${termcode or 'unknown'}) do not match any known
+    codes in the reserves system.</p>
+    <p> 
+      <a href="https://clew.uwindsor.ca/xsl-portal/site/${request.session['clew-site']}/">
+	Go back
+      </a>
+    </p>
+  </body>
+</html>

Modified: servres/trunk/conifer/integration/uwindsor.py
===================================================================
--- servres/trunk/conifer/integration/uwindsor.py	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/integration/uwindsor.py	2010-07-28 03:17:48 UTC (rev 939)
@@ -120,9 +120,14 @@
     """
     return uwindsor_campus_info.call('person_lookup', userid)
 
+def decode_role(role):
+    if role == 'Instructor':
+        return 'INSTR'
+    else:
+        return 'STUDT'
 
 def external_memberships(userid, include_titles=False):
     memberships = uwindsor_campus_info.call('membership_ids', userid)
     for m in memberships:
-        m['role'] = 'INSTR' if m['role'] == 'Instructor' else 'STUDT'
+        m['role'] = decode_role(m['role'])
     return memberships

Modified: servres/trunk/conifer/syrup/models.py
===================================================================
--- servres/trunk/conifer/syrup/models.py	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/syrup/models.py	2010-07-28 03:17:48 UTC (rev 939)
@@ -42,9 +42,12 @@
 
 class UserExtensionMixin(object):
 
-    def sites(self):
+    def sites(self, role=None):
         self.maybe_refresh_external_memberships()
-        return Site.objects.filter(group__membership__user=self.id)
+        sites = Site.objects.filter(group__membership__user=self.id)
+        if role:
+            sites = sites.filter(group__membership__role=role)
+        return sites
 
     def can_create_sites(self):
         return self.is_staff or \
@@ -122,6 +125,10 @@
     def __unicode__(self):
         return self.name
 
+    @classmethod
+    def default(cls):
+        return cls.objects.get(pk=Config.get('default.desk', 1))
+
 class Term(BaseModel):
     code   = m.CharField(max_length=64, unique=True)
     name   = m.CharField(max_length=256)
@@ -134,6 +141,8 @@
     def __unicode__(self):
         return '%s: %s' % (self.code, self.name)
 
+    def midpoint(self):
+        return self.start + timedelta(days=(self.start-self.finish).days/2)
 
 class Department(BaseModel):
     name   = m.CharField(max_length=256)

Modified: servres/trunk/conifer/urls.py
===================================================================
--- servres/trunk/conifer/urls.py	2010-07-27 02:45:15 UTC (rev 938)
+++ servres/trunk/conifer/urls.py	2010-07-28 03:17:48 UTC (rev 939)
@@ -42,5 +42,8 @@
 if settings.LINKTOOL_AUTHENTICATION:
     urlpatterns += patterns(
         'conifer.integration.linktool.app',
-        (r'^linktool-welcome/(?P<command>.*)$', 'linktool_welcome'))
-
+        (r'^linktool-welcome/$', 'linktool_welcome'),
+        (r'^linktool-welcome/new_site$', 'linktool_new_site'),
+        (r'^linktool-welcome/copy_old$', 'linktool_copy_old'),
+        (r'^linktool-welcome/associate$', 'linktool_associate'),
+        )



More information about the open-ils-commits mailing list