[open-ils-commits] r148 - in servres/trunk/conifer: . static syrup templates (gfawcett)
svn at svn.open-ils.org
svn at svn.open-ils.org
Sun Mar 8 15:08:35 EDT 2009
Author: gfawcett
Date: 2009-03-08 15:08:31 -0400 (Sun, 08 Mar 2009)
New Revision: 148
Added:
servres/trunk/conifer/static/edit_course_permissions.js
Modified:
servres/trunk/conifer/genshi_namespace.py
servres/trunk/conifer/static/main.css
servres/trunk/conifer/syrup/views.py
servres/trunk/conifer/templates/add_new_course.xhtml
servres/trunk/conifer/templates/edit_course_permissions.xhtml
Log:
better edit-course-permissions screen, separated from edit-course-details.
Still no support for course-sections; coming soon.
Modified: servres/trunk/conifer/genshi_namespace.py
===================================================================
--- servres/trunk/conifer/genshi_namespace.py 2009-03-08 17:11:14 UTC (rev 147)
+++ servres/trunk/conifer/genshi_namespace.py 2009-03-08 19:08:31 UTC (rev 148)
@@ -5,6 +5,7 @@
from itertools import cycle
from conifer.syrup import models
+import django.forms
# this probably ought to be a method on User, or another model class.
def instructor_url(instructor, suffix=''):
Added: servres/trunk/conifer/static/edit_course_permissions.js
===================================================================
--- servres/trunk/conifer/static/edit_course_permissions.js (rev 0)
+++ servres/trunk/conifer/static/edit_course_permissions.js 2009-03-08 19:08:31 UTC (rev 148)
@@ -0,0 +1,12 @@
+function do_init() {
+ show_specific_only();
+ $('#id_access').change(show_specific_only);
+}
+
+function show_specific_only() {
+ $('.specific').hide();
+ var cur = $('#id_access').val();
+ $('#' + cur + '_panel').fadeIn();
+}
+
+$(do_init);
\ No newline at end of file
Modified: servres/trunk/conifer/static/main.css
===================================================================
--- servres/trunk/conifer/static/main.css 2009-03-08 17:11:14 UTC (rev 147)
+++ servres/trunk/conifer/static/main.css 2009-03-08 19:08:31 UTC (rev 148)
@@ -49,10 +49,15 @@
border-bottom: white 10px solid;
}
+/* heading sizes and colours. */
+
h1 { font-size: 150%; }
h2 { font-size: 135%; }
-h1, h2, h3, h4 { color: navy; }
+h3 { font-size: 120%; }
+h1 { color: navy; }
+h2 { color: #066; }
+h3, h4 { color: darkgreen; }
h1 a, h2 a { color: navy; }
a { color: blue; text-decoration: none; }
@@ -209,3 +214,7 @@
font-weight: normal;
}
+.gap { height: 24; }
+
+/* panels that appear when specific OPTIONs or radio-buttons are selected. */
+.specific { padding: 8; margin: 0 16; background-color: #eef; }
Modified: servres/trunk/conifer/syrup/views.py
===================================================================
--- servres/trunk/conifer/syrup/views.py 2009-03-08 17:11:14 UTC (rev 147)
+++ servres/trunk/conifer/syrup/views.py 2009-03-08 19:08:31 UTC (rev 148)
@@ -9,6 +9,7 @@
from conifer.syrup import models
from django.contrib.auth.models import User
from django.db.models import Q
+import django.forms
from datetime import datetime
from generics import *
from gettext import gettext as _ # fixme, is this the right function to import?
@@ -136,7 +137,7 @@
class NewCourseForm(ModelForm):
class Meta:
model = models.Course
- exclude = ('passkey',)
+ exclude = ('passkey','access')
def clean_code(self):
v = (self.cleaned_data.get('code') or '').strip()
@@ -146,15 +147,7 @@
else:
raise ValidationError, _('invalid course code')
-# I want different choice labels on the access screen than are given
-# in the model.
-NewCourseForm.base_fields['access'].widget.choices = [
- (u'CLOSE', _(u'For now, just myself and designated colleagues')),
- (u'STUDT', _(u'Students in my course (I will provide section numbers)')),
- (u'INVIT', _(u'Students in my course (I will share an Invitation Code with them)')),
- (u'LOGIN', _(u'All Reserves patrons'))]
-
# hack the new-course form if we have course-code lookup
COURSE_CODE_LIST = bool(models.course_codes.course_code_list)
COURSE_CODE_LOOKUP_TITLE = bool(models.course_codes.course_code_lookup_title)
@@ -217,14 +210,73 @@
def edit_course_permissions(request, course_id):
course = get_object_or_404(models.Course, pk=course_id)
+ choose_access = django.forms.Select(choices=[
+ (u'CLOSE', _(u'No students: this site is closed.')),
+ (u'STUDT', _(u'Students in my course -- I will provide section numbers')),
+ (u'INVIT', _(u'Students in my course -- I will share an Invitation Code with them')),
+ (u'LOGIN', _(u'All Reserves patrons'))])
if request.method != 'POST':
return g.render('edit_course_permissions.xhtml', **locals())
else:
- if request.POST.get('action') == 'change_code':
+ POST = request.POST
+
+ if 'action_change_code' in POST:
+ # update invitation code -------------------------------------
course.generate_new_passkey()
+ course.access = u'INVIT'
course.save()
return HttpResponseRedirect('.')
+ elif 'action_save_instructor' in POST:
+ # update instructor details ----------------------------------
+ iname = POST.get('new_instructor_name','').strip()
+ irole = POST.get('new_instructor_role')
+
+ def get_record_for(username):
+ instr = models.maybe_initialize_user(iname)
+ if instr:
+ try:
+ return models.Member.objects.get(user=instr, course=course)
+ except models.Member.DoesNotExist:
+ return models.Member.objects.create(user=instr, course=course)
+
+ # add a new instructor
+ if iname:
+ instr = get_record_for(iname)
+ if instr: # else? should have an error.
+ instr.role = irole
+ instr.save()
+ else:
+ instructor_error = 'No such user: %s' % iname
+ return g.render('edit_course_permissions.xhtml', **locals())
+
+
+ # removing and changing roles of instructors
+ to_change_role = [(int(name.rsplit('_', 1)[-1]), POST[name]) \
+ for name in POST if name.startswith('instructor_role_')]
+ to_remove = [int(name.rsplit('_', 1)[-1]) \
+ for name in POST if name.startswith('instructor_remove_')]
+ for instr_id, newrole in to_change_role:
+ if not instr_id in to_remove:
+ instr = models.Member.objects.get(pk=instr_id, course=course)
+ instr.role = newrole
+ instr.save()
+ for instr_id in to_remove:
+ # todo, should warn if deleting yourself!
+ instr = models.Member.objects.get(pk=instr_id, course=course)
+ instr.delete()
+ # todo, should have some error-reporting.
+ return HttpResponseRedirect('.')
+
+ elif 'action_save_student' in POST:
+ # update student details ------------------------------------
+ access = POST.get('access')
+ course.access = access
+ course.save()
+ if course.access == u'STUDT':
+ raise NotImplementedError, 'No course sections yet! Coming soon.'
+ return HttpResponseRedirect('.')
+
#------------------------------------------------------------
@login_required # must be, to avoid/audit brute force attacks.
Modified: servres/trunk/conifer/templates/add_new_course.xhtml
===================================================================
--- servres/trunk/conifer/templates/add_new_course.xhtml 2009-03-08 17:11:14 UTC (rev 147)
+++ servres/trunk/conifer/templates/add_new_course.xhtml 2009-03-08 19:08:31 UTC (rev 148)
@@ -8,15 +8,15 @@
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:py="http://genshi.edgewall.org/">
<xi:include href="master.xhtml"/>
+<xi:include href="components/course.xhtml"/>
<head>
<title>${title}</title>
<script type="text/javascript" src="/static/add_new_course.js"/>
</head>
<body>
+ <div py:if="instance.id">${course_banner(instance)}</div>
<h1>${title}</h1>
- <ul py:for="fld in form" py:if="fld.errors">
- <li py:for="err in fld.errors">${fld.name}: ${err}</li>
- </ul>
+ <p py:if="instance.id"><a href="permission/">Edit course permissions</a> • <a href="${instance.course_url()}">Return to course page</a></p>
<form action="." method="POST">
<tr py:def="field_row(field, example=None)">
<th>${field.label}</th>
@@ -28,8 +28,7 @@
</td>
<td class="example" py:if="example">e.g., ${example}</td>
</tr>
- <fieldset>
- <legend>General description</legend>
+ <h2>General description</h2>
<table class="formtable">
${field_row(form.code, example)}
${field_row(form.title)}
@@ -37,12 +36,6 @@
${field_row(form.department)}
<!-- <tr><th>Department</th><td>${Markup(form.department)} ${errorlist(form.department)}</td></tr> -->
</table>
- </fieldset>
- <fieldset>
- <legend>Access controls</legend>
- <p>This site will be available to:</p>
- ${Markup(form.access)}
- </fieldset>
<p><input type="submit" value="Continue"/></p>
</form>
Modified: servres/trunk/conifer/templates/edit_course_permissions.xhtml
===================================================================
--- servres/trunk/conifer/templates/edit_course_permissions.xhtml 2009-03-08 17:11:14 UTC (rev 147)
+++ servres/trunk/conifer/templates/edit_course_permissions.xhtml 2009-03-08 19:08:31 UTC (rev 148)
@@ -1,27 +1,60 @@
<?python
title = _('Edit course permissions')
+instructors = [m for m in models.Member.objects.filter(course=course) if m.role in ('PROXY', 'INSTR')]
?>
<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="master.xhtml"/>
+ <xi:include href="components/course.xhtml"/>
<head>
<title>${title}</title>
+ <script type="text/javascript" src="/static/edit_course_permissions.js"/>
</head>
<body>
+ ${course_banner(course)}
<h1>${title}</h1>
- <h2>Add Co-Instructors and Proxies</h2>
- <p>blah blah...</p>
- <div py:choose="course.access">
- <div py:when="'INVIT'">
- <h2>Course Invitation Code</h2>
- <p style="font-size: larger;">Your Course Invitation Code is: <strong>${course.passkey}</strong></p>
- <form action="." method="POST">
- <p>
- <input type="hidden" name="action" value="change_code"/>
- <input type="submit" value="Select a new code (this will invalidate the old code!)"/>
- </p>
- </form>
+ <p><a href="../">Edit course details</a> • <a href="${course.course_url()}">Return to course page</a></p>
+ <form action="." method="POST">
+ <h2>Instructor Access</h2>
+ <div py:if="defined('instructor_error')" class="errors">${instructor_error}</div>
+ <table class="pagetable">
+ <thead>
+ <tr><th>Person</th><th>Role</th><th>Remove?</th></tr>
+ </thead>
+ <tbody>
+ <select py:def="select_role(mbr)"
+ py:replace="Markup(django.forms.Select(choices=
+ [(u'INSTR',_(u'Instructor')), (u'PROXY', _(u'Proxy instructor'))])
+ .render('instructor_role_%d' % mbr.id, mbr.role))"/>
+ <tr py:for="mbr in instructors">
+ <td>${mbr.user.get_full_name() or mbr.user}</td>
+ <td>${select_role(mbr)}</td>
+ <td><input type="checkbox" name="instructor_remove_${mbr.id}"/></td>
+ </tr>
+ <tr style="vertical-align: bottom;">
+ <td><p>Username of the new instructor.</p><input type="text" name="new_instructor_name"/></td>
+ <td><select name="new_instructor_role">
+ <option value="INSTR">Instructor</option>
+ <option value="PROXY">Proxy instructor</option>
+ </select>
+ </td>
+ <td/>
+ </tr>
+ </tbody>
+ </table>
+ <p> <input type="submit" name="action_save_instructor" value="Save changes to instructors"/></p>
+ <div class="gap"/>
+ <h2>Student Access</h2>
+ <p>Who will have student-level access to this site?
+ <span style="margin-left: 12;"/>${Markup(choose_access.render('access', course.access, {'id':'id_access'}, []))}</p>
+ <div id="INVIT_panel" class="specific">
+ <h3>Course Invitation Code</h3>
+ <p style="font-size: larger;">Your Course Invitation Code is: <strong>${course.passkey}</strong>
+ <span style="margin-left: 16;">
+ <input type="submit" name="action_change_code" value="Select a new code"/>
+ </span>
+ </p>
<p>This invitation code will enable your students to join this
course site. Share it only with your students: anyone who has
the code can join your site.</p>
@@ -29,10 +62,19 @@
students who have already joined, but will prevent new students
from joining with the old code.</p>
</div>
- <div py:when="'STUDT'">
- <h2>Course section numbers</h2>
+ <div id="STUDT_panel" class="specific">
+ <h3>Course section numbers</h3>
+ <table>
+ <tr py:for="x in range(3)"><td><input type="text"/></td></tr>
+ </table>
</div>
- </div>
+ <p><input type="submit" name="action_save_student" value="Save changes to student access"/></p>
+
+ <div class="gap"/>
+ <h2>Class List</h2>
+ <p>The following users have student-level access in this course site.</p>
+
+ </form>
<div class="gap"/>
</body>
</html>
More information about the open-ils-commits
mailing list