From: gfawcett Date: Thu, 15 Jul 2010 00:54:04 +0000 (+0000) Subject: semi-mechanical translation from 'course' to 'site' inside files. X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=ba3952b3b865f2bdf7754f342f520cdf403e3a64;p=Syrup.git semi-mechanical translation from 'course' to 'site' inside files. I'm sure I messed some things up, but it's much closer to being good! git-svn-id: svn://svn.open-ils.org/ILS-Contrib/servres/trunk@909 6d9bc8c9-1ec2-4278-b937-99fde70a366f --- diff --git a/conifer/genshi_namespace.py b/conifer/genshi_namespace.py index f2424f9..154342a 100644 --- a/conifer/genshi_namespace.py +++ b/conifer/genshi_namespace.py @@ -24,9 +24,9 @@ def call_or_value(obj, dflt=None): return obj or dflt -def instructs(user, course): +def instructs(user, site): try: - mbr = models.Member.objects.get(user=user, course=course) + mbr = models.Member.objects.get(user=user, site=site) return mbr.role in ('INSTR', 'PROXY') except: return False diff --git a/conifer/static/edit_site.js b/conifer/static/edit_site.js index 88022cd..c705a70 100644 --- a/conifer/static/edit_site.js +++ b/conifer/static/edit_site.js @@ -3,7 +3,7 @@ function do_init() { // code is a SELECT, so we add a callback to lookup titles. $('#id_code').change(function() { $('#id_title')[0].disabled=true; - $.getJSON(ROOT + '/course/new/ajax_title', {course_code: $(this).val()}, + $.getJSON(ROOT + '/site/new/ajax_title', {course_code: $(this).val()}, function(resp) { $('#id_title').val(resp.title) $('#id_title')[0].disabled=false; diff --git a/conifer/static/main.css b/conifer/static/main.css index 0729361..7403ddc 100644 --- a/conifer/static/main.css +++ b/conifer/static/main.css @@ -152,7 +152,7 @@ a:hover { text-decoration: underline; } span.final_item { font-weight: bold; font-size: 110%; } -/* item trees (tree of headings and items in a course */ +/* item trees (tree of headings and items in a site */ #sidepanel { width: 183px; float: right; text-align: right;} #sidepanel div { margin: 6px 0; } @@ -281,11 +281,11 @@ p.todo, div.todo { background-color: #fdd; padding: 6px; margin: 12px; border-le .menublockopener { margin-left: 0.25em; color: #bbb !important; font-weight: normal !important; } .menublock { background-color: #f2e4cc; font-size: 95%; padding: 1px 4px; } -#coursebanner { background-color: #f2e4cc; margin: -12px -12px 12px -12px; padding: 8px; } -#coursesearch { float: right; } -#coursebanner h1 { margin: 12px 0; font-size: 125%; } +#sitebanner { background-color: #f2e4cc; margin: -12px -12px 12px -12px; padding: 8px; } +#sitesearch { float: right; } +#sitebanner h1 { margin: 12px 0; font-size: 125%; } -#edit_course_link { margin: 8px 0 8px 0; font-size: 95%; } +#edit_site_link { margin: 8px 0 8px 0; font-size: 95%; } #breadcrumbs { margin: 8px 0px 16px 0; width: 716px; diff --git a/conifer/static/menublocks.js b/conifer/static/menublocks.js index a00f57c..7c3c01e 100644 --- a/conifer/static/menublocks.js +++ b/conifer/static/menublocks.js @@ -49,7 +49,7 @@ $(init_blocks); // fixme, I need to rename menublocks.js to something more like -// 'course-item-stuff.js'. +// 'site-item-stuff.js'. // this is some item resequencing code. diff --git a/conifer/syrup/models.py b/conifer/syrup/models.py index c8aee0c..93ec273 100644 --- a/conifer/syrup/models.py +++ b/conifer/syrup/models.py @@ -37,7 +37,7 @@ class BaseModel(m.Model): # General methods that return sets of users (e.g. all instructors, all # staff) -- let's put those on the UserProfile class, as class -# methods. For now, let's put personal methods (e.g. my courses) on +# methods. For now, let's put personal methods (e.g. my sites) on # the User object (although UserProfile would be another logical # candidate). @@ -186,7 +186,7 @@ class Site(BaseModel): def item_tree(self, subtree=None): """ - Return a list, representing a tree of the course items, in + Return a list, representing a tree of the site items, in display order. Every element of the list is an (Item, [Item]) tuple, where the second element is a list of sub-elements (if a heading) or None (if an item). @@ -214,12 +214,12 @@ class Site(BaseModel): walk(subtree, out) return out - def course_url(self, suffix=''): + def site_url(self, suffix=''): # I'm not fond of this being here. I think I'll leave this and # item_url non-implemented, and monkey-patch them in views.py. req = genshi_locals.get_request() prefix = req.META['SCRIPT_NAME'] - return '%s/course/%d/%s' % (prefix, self.id, suffix) + return '%s/site/%d/%s' % (prefix, self.id, suffix) def generate_new_passkey(self): # todo: have a pluggable passkey algorithm. @@ -261,7 +261,7 @@ class Site(BaseModel): def is_joinable_by(self, user): """Return True if the user could feasibly register into this - course: she's not already in it, and the course allows open + site: she's not already in it, and the site allows open registration.""" return user.is_authenticated() \ and self.access in ('ANON', 'LOGIN') \ @@ -466,24 +466,24 @@ class Item(BaseModel): def item_url(self, suffix='', force_local_url=False): # I'm not fond of this being here. I think I'll leave this and - # course_url non-implemented, and monkey-patch them in views.py. + # site_url non-implemented, and monkey-patch them in views.py. req = genshi_locals.get_request() prefix = req.META['SCRIPT_NAME'] if self.item_type == 'ELEC' and suffix == '': - return '%s/course/%d/item/%d/dl/%s' % ( - prefix, self.course_id, self.id, + return '%s/site/%d/item/%d/dl/%s' % ( + prefix, self.site_id, self.id, self.fileobj.name.split('/')[-1]) if self.item_type == 'URL' and suffix == '' and not force_local_url: return self.url else: - return '%s/course/%d/item/%d/%s' % ( - prefix, self.course_id, self.id, suffix) + return '%s/site/%d/item/%d/%s' % ( + prefix, self.site_id, self.id, suffix) def parent_url(self, suffix=''): if self.parent_heading: return self.parent_heading.item_url() else: - return self.course.course_url() + return self.site.site_url() def describe_physical_item_status(self): """Return a (bool,str) tuple: whether the item is available, diff --git a/conifer/syrup/urls.py b/conifer/syrup/urls.py index 39c8729..8e17a4e 100644 --- a/conifer/syrup/urls.py +++ b/conifer/syrup/urls.py @@ -3,21 +3,21 @@ from django.conf.urls.defaults import * # I'm not ready to break items out into their own urls.py, but I do # want to cut down on the common boilerplate in the urlpatterns below. -ITEM_PREFIX = r'^course/(?P\d+)/item/(?P\d+)/' +ITEM_PREFIX = r'^site/(?P\d+)/item/(?P\d+)/' GENERIC_REGEX = r'((?P\d+)/)?(?P.+)?$' urlpatterns = patterns('conifer.syrup.views', (r'^$', 'welcome'), - (r'^course/$', 'my_courses'), - (r'^course/new/$', 'add_new_course'), - (r'^course/new/ajax_title$', 'add_new_course_ajax_title'), - (r'^course/invitation/$', 'course_invitation'), + (r'^site/$', 'my_sites'), + (r'^site/new/$', 'add_new_site'), + (r'^site/new/ajax_title$', 'add_new_site_ajax_title'), + (r'^site/invitation/$', 'site_invitation'), (r'^browse/$', 'browse'), (r'^browse/(?P.*)/$', 'browse'), (r'^prefs/$', 'user_prefs'), (r'^z3950test/$', 'z3950_test'), - #MARK: propose we kill open_courses, we have browse. - (r'^opencourse/$', 'open_courses'), + #MARK: propose we kill open_sites, we have browse. + (r'^opensite/$', 'open_sites'), (r'^search/$', 'search'), (r'^zsearch/$', 'zsearch'), #MARK: propose we kill instructors, we have browse @@ -25,15 +25,15 @@ urlpatterns = patterns('conifer.syrup.views', (r'^instructors/search/(?P.*)$', 'instructor_search'), #MARK: propose we kill departments, we have browse (r'^departments/$', 'departments'), - (r'^course/(?P\d+)/$', 'course_detail'), + (r'^site/(?P\d+)/$', 'site_detail'), (r'^instructor/(?P.*)/$', 'instructor_detail'), (r'^department/(?P.*)/$', 'department_detail'), - (r'^course/(?P\d+)/search/$', 'course_search'), - (r'^course/(?P\d+)/edit/$', 'edit_course'), - (r'^course/(?P\d+)/edit/delete/$', 'delete_course'), - (r'^course/(?P\d+)/edit/permission/$', 'edit_course_permissions'), - (r'^course/(?P\d+)/feeds/(?P.*)$', 'course_feeds'), - (r'^course/(?P\d+)/join/$', 'course_join'), + (r'^site/(?P\d+)/search/$', 'site_search'), + (r'^site/(?P\d+)/edit/$', 'edit_site'), + (r'^site/(?P\d+)/edit/delete/$', 'delete_site'), + (r'^site/(?P\d+)/edit/permission/$', 'edit_site_permissions'), + (r'^site/(?P\d+)/feeds/(?P.*)$', 'site_feeds'), + (r'^site/(?P\d+)/join/$', 'site_join'), (ITEM_PREFIX + r'$', 'item_detail'), (ITEM_PREFIX + r'dl/(?P.*)$', 'item_download'), (ITEM_PREFIX + r'meta$', 'item_metadata'), @@ -56,7 +56,7 @@ urlpatterns = patterns('conifer.syrup.views', (r'^phys/mark_arrived/match/$', 'phys_mark_arrived_match'), (r'^phys/circlist/$', 'phys_circlist'), - (r'^course/(?P\d+)/reseq$', 'course_reseq'), + (r'^site/(?P\d+)/reseq$', 'site_reseq'), (ITEM_PREFIX + r'reseq', 'item_heading_reseq'), (ITEM_PREFIX + r'relocate/', 'item_relocate'), # move to new subheading # (r'^admin/terms/(?P\d+)/$', 'admin_term_edit'), diff --git a/conifer/syrup/views/__init__.py b/conifer/syrup/views/__init__.py index 0974800..e308320 100644 --- a/conifer/syrup/views/__init__.py +++ b/conifer/syrup/views/__init__.py @@ -1,6 +1,6 @@ from conifer.integration import hooks from general import * -from courses import * +from sites import * from items import * from search import * from admin import * diff --git a/conifer/syrup/views/_common.py b/conifer/syrup/views/_common.py index f09d844..428fad7 100644 --- a/conifer/syrup/views/_common.py +++ b/conifer/syrup/views/_common.py @@ -107,16 +107,18 @@ def auth_handler(request, path): #----------------------------------------------------------------------------- # Authorization -def _fast_user_membership_query(user_id, course_id, where=None): +# TODO: this _fast_user_membership_query is broken. + +def _fast_user_membership_query(user_id, site_id, where=None): # I use a raw SQL query here because I want the lookup to be as # fast as possible. Caching would help too, but let's try this # first. (todo, review later.) query = ('select count(*) from syrup_member ' - 'where user_id=%s and course_id=%s ') + 'where user_id=%s and site_id=%s ') if where: query += (' and ' + where) cursor = django.db.connection.cursor() - cursor.execute(query, [user_id, int(course_id)]) + cursor.execute(query, [user_id, int(site_id)]) res = cursor.fetchall() cursor.close() allowed = bool(res[0][0]) @@ -136,13 +138,13 @@ def _access_denied(request, message): # decorator def instructors_only(handler): - def hdlr(request, course_id, *args, **kwargs): + def hdlr(request, site_id, *args, **kwargs): allowed = request.user.is_superuser if not allowed: allowed = _fast_user_membership_query( - request.user.id, course_id, "role in ('INSTR','PROXY')") + request.user.id, site_id, "role in ('INSTR','ASSIST')") if allowed: - return handler(request, course_id, *args, **kwargs) + return handler(request, site_id, *args, **kwargs) else: return _access_denied(request, _('Only instructors are allowed here.')) @@ -150,22 +152,22 @@ def instructors_only(handler): # decorator def members_only(handler): - def hdlr(request, course_id, *args, **kwargs): + def hdlr(request, site_id, *args, **kwargs): user = request.user allowed = user.is_superuser if not allowed: - course = models.ReadingList.objects.get(pk=course_id) - allowed = course.access=='ANON' or \ - (user.is_authenticated() and course.access=='LOGIN') + site = models.Site.objects.get(pk=site_id) + allowed = site.access=='ANON' or \ + (user.is_authenticated() and site.access=='LOGIN') if not allowed: - allowed = _fast_user_membership_query(user.id, course_id) + allowed = _fast_user_membership_query(user.id, site_id) if allowed: - return handler(request, course_id, *args, **kwargs) + return handler(request, site_id, *args, **kwargs) else: - if course.access=='LOGIN': + if site.access=='LOGIN': msg = _('Please log in, so that you can enter this site.') else: - msg = _('Only course members are allowed here.') + msg = _('Only site members are allowed here.') return _access_denied(request, msg) return hdlr @@ -212,24 +214,24 @@ def custom_400_handler(request): #----------------------------------------------------------- def user_filters(user): - """Returns a dict of filters for Item, ReadingList, etc. querysets, + """Returns a dict of filters for Item, Site, etc. querysets, based on the given user's permissions.""" # TODO, figure out a way of EXPLAIN'ing these queries! I have no # idea of their complexity. if user.is_anonymous(): - # then only anonymous-access courses are available. - filters = {'items': Q(course__access='ANON'), - 'courses': Q(access='ANON'), + # then only anonymous-access sites are available. + filters = {'items': Q(site__access='ANON'), + 'sites': Q(access='ANON'), 'instructors': Q(), # TODO: do we really need a filter here? } else: - # logged-in users have access to courses which are of the + # logged-in users have access to sites which are of the # LOGIN class ('all logged-in users') or in which they # have explicit Member-ship. filters = { - 'items': (Q(course__access__in=('LOGIN','ANON')) \ - | Q(course__member__user=user)), - 'courses': (Q(access__in=('LOGIN','ANON')) | Q(member__user=user)), + 'items': (Q(site__access__in=('LOGIN','ANON')) \ + | Q(site__member__user=user)), + 'sites': (Q(access__in=('LOGIN','ANON')) | Q(member__user=user)), 'instructors': Q(), # TODO: do we really need a filter here? } return filters diff --git a/conifer/syrup/views/feeds.py b/conifer/syrup/views/feeds.py index b10552e..ce17953 100644 --- a/conifer/syrup/views/feeds.py +++ b/conifer/syrup/views/feeds.py @@ -2,16 +2,16 @@ from _common import * from django.utils.translation import ugettext as _ #----------------------------------------------------------------------------- -# Course feeds +# Site feeds @public # and proud of it! -def course_feeds(request, course_id, feed_type): - course = get_object_or_404(models.Course, pk=course_id) +def site_feeds(request, site_id, feed_type): + site = get_object_or_404(models.Site, pk=site_id) if feed_type == '': - return g.render('feeds/course_feed_index.xhtml', - course=course) + return g.render('feeds/site_feed_index.xhtml', + site=site) else: - items = course.items() + items = site.items() def render_title(item): return item.title if feed_type == 'top-level': @@ -25,15 +25,15 @@ def course_feeds(request, course_id, feed_type): acc.append(item) flatten(kids, acc) return acc - items = flatten(course.item_tree(), []) + items = flatten(site.item_tree(), []) def render_title(item): if item.parent_heading: return '%s :: %s' % (item.parent_heading.title, item.title) else: return item.title lastmod = items and max(i.last_modified for i in items) or datetime.now() - resp = g.render('feeds/course_atom.xml', - course=course, + resp = g.render('feeds/site_atom.xml', + site=site, feed_type=feed_type, lastmod=lastmod, render_title=render_title, diff --git a/conifer/syrup/views/general.py b/conifer/syrup/views/general.py index 4ab6ad8..1b058da 100644 --- a/conifer/syrup/views/general.py +++ b/conifer/syrup/views/general.py @@ -11,12 +11,12 @@ import os def welcome(request): return HttpResponseRedirect('browse/') -# MARK: propose we get rid of this. We already have a 'Courses' browser. -def open_courses(request): +# MARK: propose we get rid of this. We already have a 'Sites' browser. +def open_sites(request): page_num = int(request.GET.get('page', 1)) count = int(request.GET.get('count', 5)) - paginator = Paginator(models.ReadingList.objects.all(), count) # fixme, what filter? - return g.render('open_courses.xhtml', paginator=paginator, + paginator = Paginator(models.Site.objects.all(), count) # fixme, what filter? + return g.render('open_sites.xhtml', paginator=paginator, page_num=page_num, count=count) # MARK: propose we drop this too. We have a browse. @@ -27,9 +27,9 @@ def instructors(request): if action == 'join': paginator = Paginator(models.User.active_instructors(), count) elif action == 'drop': - paginator = Paginator(models.ReadingList.objects.all(), count) # fixme, what filter? + paginator = Paginator(models.Site.objects.all(), count) # fixme, what filter? else: - paginator = Paginator(models.ReadingList.objects.all(), count) # fixme, what filter? + paginator = Paginator(models.Site.objects.all(), count) # fixme, what filter? return g.render('instructors.xhtml', paginator=paginator, page_num=page_num, @@ -104,7 +104,7 @@ def browse(request, browse_option=''): elif browse_option == 'courses': # fixme, course filter should not be (active=True) but based on user identity. for_courses = user_filters(request.user)['courses'] - queryset = models.ReadingList.objects.filter(for_courses) + queryset = models.Site.objects.filter(for_courses) template = 'courses.xhtml' queryset = queryset and queryset.distinct() @@ -114,17 +114,17 @@ def browse(request, browse_option=''): count=count) @login_required -def my_courses(request): - return g.render('my_courses.xhtml') +def my_sites(request): + return g.render('my_sites.xhtml') def instructor_detail(request, instructor_id): page_num = int(request.GET.get('page', 1)) count = int(request.GET.get('count', 5)) ''' i am not sure this is the best way to go from instructor - to course + to site ''' - courses = models.ReadingList.objects.filter(member__user=instructor_id, + sites = models.Site.objects.filter(member__user=instructor_id, member__role='INSTR') filters = user_filters(request.user) courses = courses.filter(filters['courses']) @@ -146,7 +146,7 @@ def department_detail(request, department_id): page_num = int(request.GET.get('page', 1)) count = int(request.GET.get('count', 5)) - paginator = Paginator(models.ReadingList.objects. + paginator = Paginator(models.Site.objects. filter(department__id=department_id). order_by('title'), count) diff --git a/conifer/syrup/views/items.py b/conifer/syrup/views/items.py index 1bb08d8..44e7ed0 100644 --- a/conifer/syrup/views/items.py +++ b/conifer/syrup/views/items.py @@ -2,26 +2,26 @@ from _common import * from django.utils.translation import ugettext as _ @members_only -def item_detail(request, course_id, item_id): +def item_detail(request, site_id, item_id): """Display an item (however that makes sense).""" # really, displaying an item will vary based on what type of item # it is -- e.g. a URL item would redirect to the target URL. I'd # like this URL to be the generic dispatcher, but for now let's # just display some metadata about the item. - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) if item.url: return _heading_url(request, item) else: - return item_metadata(request, course_id, item_id) + return item_metadata(request, site_id, item_id) @members_only -def item_metadata(request, course_id, item_id): +def item_metadata(request, site_id, item_id): """Display a metadata page for the item.""" - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) if item.item_type == 'HEADING': return _heading_detail(request, item) else: - return g.render('item/item_metadata.xhtml', course=item.course, + return g.render('item/item_metadata.xhtml', site=item.site, item=item) def _heading_url(request, item): @@ -33,7 +33,7 @@ def _heading_detail(request, item): @instructors_only -def item_add(request, course_id, item_id): +def item_add(request, site_id, item_id): # The parent_item_id is the id for the parent-heading item. Zero # represents 'top-level', i.e. the new item should have no # heading. @@ -42,19 +42,19 @@ def item_add(request, course_id, item_id): parent_item_id = item_id if parent_item_id=='0': parent_item = None - course = get_object_or_404(models.Course, pk=course_id) - siblings = course.item_set.filter(parent_heading=None) + site = get_object_or_404(models.Site, pk=site_id) + siblings = site.item_set.filter(parent_heading=None) else: - parent_item = get_object_or_404(models.Item, pk=parent_item_id, course__id=course_id) + parent_item = get_object_or_404(models.Item, pk=parent_item_id, site__id=site_id) assert parent_item.item_type == 'HEADING', _('You can only add items to headings!') - course = parent_item.course - siblings = course.item_set.filter(parent_heading=parent_item) + site = parent_item.site + siblings = site.item_set.filter(parent_heading=parent_item) try: next_order = 1 + max(i.sort_order for i in siblings) except: next_order = 0 - if not course.can_edit(request.user): + if not site.can_edit(request.user): return _access_denied(_('You are not an editor.')) item_type = request.GET.get('item_type') @@ -91,7 +91,7 @@ def item_add(request, course_id, item_id): return HttpResponseRedirect(request.get_full_path()) else: item = models.Item( - course=course, + site=site, item_type='HEADING', sort_order = next_order, parent_heading=parent_item, @@ -108,7 +108,7 @@ def item_add(request, course_id, item_id): return HttpResponseRedirect(request.get_full_path()) else: item = models.Item( - course=course, + site=site, item_type='URL', parent_heading=parent_item, sort_order = next_order, @@ -124,7 +124,7 @@ def item_add(request, course_id, item_id): # fixme, better error handling. return HttpResponseRedirect(request.get_full_path()) item = models.Item( - course=course, + site=site, item_type='ELEC', parent_heading=parent_item, sort_order = next_order, @@ -141,21 +141,21 @@ def item_add(request, course_id, item_id): if parent_item: return HttpResponseRedirect(parent_item.item_url('meta')) else: - return HttpResponseRedirect(course.course_url()) + return HttpResponseRedirect(site.site_url()) @instructors_only -def item_add_cat_search(request, course_id, item_id): +def item_add_cat_search(request, site_id, item_id): # this chunk stolen from item_add(). Refactor. parent_item_id = item_id if parent_item_id=='0': parent_item = None - course = get_object_or_404(models.Course, pk=course_id) - siblings = course.item_set.filter(parent_heading=None) + site = get_object_or_404(models.Site, pk=site_id) + siblings = site.item_set.filter(parent_heading=None) else: - parent_item = get_object_or_404(models.Item, pk=parent_item_id, course__id=course_id) + parent_item = get_object_or_404(models.Item, pk=parent_item_id, site__id=site_id) assert parent_item.item_type == 'HEADING', _('You can only add items to headings!') - course = parent_item.course - siblings = course.item_set.filter(parent_heading=parent_item) + site = parent_item.site + siblings = site.item_set.filter(parent_heading=parent_item) try: next_order = 1 + max(i.sort_order for i in siblings) @@ -167,28 +167,28 @@ def item_add_cat_search(request, course_id, item_id): if request.method != 'POST': if not 'query' in request.GET: return g.render('item/item_add_cat_search.xhtml', results=[], query='', - course=course, parent_item=parent_item) + site=site, parent_item=parent_item) query = request.GET.get('query','').strip() start, limit = (int(request.GET.get(k,v)) for k,v in (('start',1),('limit',10))) results, numhits = lib_integration.cat_search(query, start, limit) return g.render('item/item_add_cat_search.xhtml', results=results, query=query, start=start, limit=limit, numhits=numhits, - course=course, parent_item=parent_item) + site=site, parent_item=parent_item) else: - # User has selected an item; add it to course site. + # User has selected an item; add it to site. raw_pickitem = request.POST.get('pickitem', '').strip() #fixme, this block copied from item_add. refactor. parent_item_id = item_id if parent_item_id == '0': # no heading (toplevel) parent_item = None - course = get_object_or_404(models.Course, pk=course_id) + site = get_object_or_404(models.Site, pk=site_id) else: - parent_item = get_object_or_404(models.Item, pk=parent_item_id, course__id=course_id) + parent_item = get_object_or_404(models.Item, pk=parent_item_id, site__id=site_id) assert parent_item.item_type == 'HEADING', _('You can only add items to headings!') - course = parent_item.course - if not course.can_edit(request.user): + site = parent_item.site + if not site.can_edit(request.user): return _access_denied(_('You are not an editor.')) pickitem = simplejson.loads(raw_pickitem) @@ -202,7 +202,7 @@ def item_add_cat_search(request, course_id, item_id): else: dct = dict(item_type='PHYS') - item = course.item_set.create(parent_heading=parent_item, + item = site.item_set.create(parent_heading=parent_item, sort_order=next_order, title=dublin.get('dc:title','Untitled'), **dct) @@ -218,9 +218,9 @@ def item_add_cat_search(request, course_id, item_id): #------------------------------------------------------------ @instructors_only -def item_edit(request, course_id, item_id): - course = get_object_or_404(models.Course, pk=course_id) - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) +def item_edit(request, site_id, item_id): + site = get_object_or_404(models.Site, pk=site_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) item_type = item.item_type template = 'item/item_add_%s.xhtml' % item_type.lower() parent_item = item.parent_heading @@ -249,9 +249,9 @@ def item_edit(request, course_id, item_id): return HttpResponseRedirect(item.parent_url()) @instructors_only -def item_delete(request, course_id, item_id): - course = get_object_or_404(models.Course, pk=course_id) - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) +def item_delete(request, site_id, item_id): + site = get_object_or_404(models.Site, pk=site_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) if request.method != 'POST': return g.render('item/item_delete_confirm.xhtml', **locals()) else: @@ -261,16 +261,16 @@ def item_delete(request, course_id, item_id): if item.parent_heading: redir = HttpResponseRedirect(item.parent_heading.item_url('meta')) else: - redir = HttpResponseRedirect(course.course_url()) + redir = HttpResponseRedirect(site.site_url()) item.delete() return redir else: return HttpResponseRedirect('../meta') @members_only -def item_download(request, course_id, item_id, filename): - course = get_object_or_404(models.Course, pk=course_id) - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) +def item_download(request, site_id, item_id, filename): + site = get_object_or_404(models.Site, pk=site_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) assert item.item_type == 'ELEC', _('Can only download ELEC documents!') fileiter = item.fileobj.chunks() resp = HttpResponse(fileiter) @@ -283,13 +283,13 @@ def item_download(request, course_id, item_id, filename): #------------------------------------------------------------ # resequencing items -def _reseq(request, course, parent_heading): +def _reseq(request, site, parent_heading): new_order = request.POST['new_order'].strip().split(' ') # new_order is now a list like this: ['item_3', 'item_8', 'item_1', ...]. # get at the ints. new_order = [int(n.split('_')[1]) for n in new_order] print >> sys.stderr, new_order - the_items = list(course.item_set.filter(parent_heading=parent_heading).order_by('sort_order')) + the_items = list(site.item_set.filter(parent_heading=parent_heading).order_by('sort_order')) # sort the items by position in new_order the_items.sort(key=lambda item: new_order.index(item.id)) for newnum, item in enumerate(the_items): @@ -298,24 +298,24 @@ def _reseq(request, course, parent_heading): return HttpResponse("'ok'"); @instructors_only -def course_reseq(request, course_id): - course = get_object_or_404(models.Course, pk=course_id) +def site_reseq(request, site_id): + site = get_object_or_404(models.Site, pk=site_id) parent_heading = None - return _reseq(request, course, parent_heading) + return _reseq(request, site, parent_heading) @instructors_only -def item_heading_reseq(request, course_id, item_id): - course = get_object_or_404(models.Course, pk=course_id) - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) +def item_heading_reseq(request, site_id, item_id): + site = get_object_or_404(models.Site, pk=site_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) parent_heading = item - return _reseq(request, course, parent_heading) + return _reseq(request, site, parent_heading) @instructors_only -def item_relocate(request, course_id, item_id): +def item_relocate(request, site_id, item_id): """Move an item from its current subheading to another one.""" - course = get_object_or_404(models.Course, pk=course_id) - item = get_object_or_404(models.Item, pk=item_id, course__id=course_id) + site = get_object_or_404(models.Site, pk=site_id) + item = get_object_or_404(models.Item, pk=item_id, site__id=site_id) if request.method != 'POST': return g.render('item/item_relocate.xhtml', **locals()) else: @@ -323,7 +323,7 @@ def item_relocate(request, course_id, item_id): if newheading == 0: new_parent = None else: - new_parent = course.item_set.get(pk=newheading) + new_parent = site.item_set.get(pk=newheading) if item in new_parent.hierarchy(): # then we would create a cycle. Bail out. return simple_message(_('Impossible item-move!'), @@ -333,7 +333,7 @@ def item_relocate(request, course_id, item_id): if new_parent: return HttpResponseRedirect(new_parent.item_url('meta')) else: - return HttpResponseRedirect(course.course_url()) + return HttpResponseRedirect(site.site_url()) @@ -496,7 +496,7 @@ def phys_circlist(request): cursor.close() wanted = models.Item.objects.filter( - item_type='PHYS', course__term=term).select_related('metadata') + item_type='PHYS', site__term=term).select_related('metadata') wanted = [w for w in wanted if w.id not in bad_ids] return g.render('phys/circlist_for_term.xhtml', term=term, diff --git a/conifer/syrup/views/search.py b/conifer/syrup/views/search.py index 719f7b4..62f911c 100644 --- a/conifer/syrup/views/search.py +++ b/conifer/syrup/views/search.py @@ -39,15 +39,15 @@ def get_query(query_string, search_fields): #----------------------------------------------------------------------------- # Search and search support -def search(request, in_course=None, with_instructor=None): +def search(request, in_site=None, with_instructor=None): ''' Need to work on this, the basic idea is - - put an entry point for instructor and course listings + - put an entry point for instructor and site listings - page through item entries - If in_course is provided, then limit search to the contents of the specified course. + If in_site is provided, then limit search to the contents of the specified site. If with_instructor is provided, then limit search to instructors ''' - print("in_couse is %s" % in_course) + print("in_couse is %s" % in_site) print("with_instructor is %s" % with_instructor) found_entries = None page_num = int(request.GET.get('page', 1)) @@ -69,7 +69,7 @@ def search(request, in_course=None, with_instructor=None): # Next, we filter based on user permissions. flt = user_filters(request.user) - user_filter_for_items, user_filter_for_courses = flt['items'], flt['courses'] + user_filter_for_items, user_filter_for_sites = flt['items'], flt['sites'] # Note, we haven't user-filtered anything yet; we've just set # up the filters. @@ -92,11 +92,11 @@ def search(request, in_course=None, with_instructor=None): #need to think about sort order here, probably better by author (will make sortable at display level) results_list = models.Item.objects.filter(item_query) - if in_course: - # For an in-course search, we know the user has - # permissions to view the course; no need for + if in_site: + # For an in-site search, we know the user has + # permissions to view the site; no need for # user_filter_for_items. - results_list = results_list.filter(course=in_course) + results_list = results_list.filter(site=in_site) elif with_instructor: print("in instructor") results_list = results_list.filter(instructor=with_instructor) @@ -107,38 +107,38 @@ def search(request, in_course=None, with_instructor=None): results_len = len(results_list) paginator = Paginator(results_list, count) - #course search - if in_course: - # then no course search is necessary. - course_list = []; course_len = 0 + #site search + if in_site: + # then no site search is necessary. + site_list = []; site_len = 0 else: - course_query = get_query(query_string, ['title', 'department__name']) + site_query = get_query(query_string, ['title', 'department__name']) # apply the search-filter and the user-filter - course_results = models.ReadingList.objects.filter(course_query).filter(user_filter_for_courses) - course_list = course_results.order_by('title') - course_len = len(course_results) + site_results = models.Site.objects.filter(site_query).filter(user_filter_for_sites) + site_list = site_results.order_by('title') + site_len = len(site_results) #instructor search - if in_course: + if in_site: instructor_list = []; instr_len = 0 else: instr_query = get_query(query_string, ['user__last_name']) instructor_results = models.Member.objects.filter(instr_query).filter(role='INSTR') - if in_course: - instructor_results = instructor_results.filter(course=in_course) + if in_site: + instructor_results = instructor_results.filter(site=in_site) instructor_list = instructor_results.order_by('user__last_name')[0:5] instr_len = len(instructor_results) - elif in_course: - # we are in a course, but have no query? Return to the course-home page. + elif in_site: + # we are in a site, but have no query? Return to the site-home page. return HttpResponseRedirect('../') else: results_list = models.Item.objects.order_by('title') results_len = len(results_list) paginator = Paginator( results_list, count) - course_results = models.ReadingList.objects.filter(active=True) - course_list = course_results.order_by('title')[0:5] - course_len = len(course_results) + site_results = models.Site.objects.filter(active=True) + site_list = site_results.order_by('title')[0:5] + site_len = len(site_results) instructor_results = models.Member.objects.filter(role='INSTR') instructor_list = instructor_results.order_by('user__last_name')[0:5] instr_len = len(instructor_results) diff --git a/conifer/syrup/views/sites.py b/conifer/syrup/views/sites.py index e4b85ba..f95c96b 100644 --- a/conifer/syrup/views/sites.py +++ b/conifer/syrup/views/sites.py @@ -3,11 +3,11 @@ from django.utils.translation import ugettext as _ from search import * #----------------------------------------------------------------------------- -# Creating a new course +# Creating a new site -class NewCourseForm(ModelForm): +class NewSiteForm(ModelForm): class Meta: - model = models.Course + model = models.Site exclude = ('passkey','access') def clean_code(self): @@ -30,63 +30,63 @@ if COURSE_CODE_LIST: choices.sort() empty_label = u'---------' choices.insert(0, ('', empty_label)) - NewCourseForm.base_fields['code'].widget = Select( + NewSiteForm.base_fields['code'].widget = Select( choices = choices) - NewCourseForm.base_fields['code'].empty_label = empty_label + NewSiteForm.base_fields['code'].empty_label = empty_label #-------------------- @login_required -def add_new_course(request): - if not request.user.can_create_reading_lists(): - return _access_denied(_('You are not allowed to create course sites.')) - return _add_or_edit_course(request) +def add_new_site(request): + if not request.user.can_create_sites(): + return _access_denied(_('You are not allowed to create sites.')) + return _add_or_edit_site(request) @instructors_only -def edit_course(request, course_id): - instance = get_object_or_404(models.Course, pk=course_id) - return _add_or_edit_course(request, instance=instance) +def edit_site(request, site_id): + instance = get_object_or_404(models.Site, pk=site_id) + return _add_or_edit_site(request, instance=instance) -def _add_or_edit_course(request, instance=None): +def _add_or_edit_site(request, instance=None): is_add = (instance is None) if is_add: - instance = models.Course() + instance = models.Site() current_access_level = not is_add and instance.access or None example = models.campus.course_code_example if request.method != 'POST': - form = NewCourseForm(instance=instance) - return g.render('edit_course.xhtml', **locals()) + form = NewSiteForm(instance=instance) + return g.render('edit_site.xhtml', **locals()) else: - form = NewCourseForm(request.POST, instance=instance) + form = NewSiteForm(request.POST, instance=instance) if not form.is_valid(): - return g.render('edit_course.xhtml', **locals()) + return g.render('edit_site.xhtml', **locals()) else: form.save() - course = form.instance - if course.access == u'INVIT' and not course.passkey: - course.generate_new_passkey() - course.save() - assert course.id - user_in_course = models.Member.objects.filter(user=request.user,course=course) - if not user_in_course: # for edits, might already be! - mbr = course.member_set.create(user=request.user, role='INSTR') + site = form.instance + if site.access == u'INVIT' and not site.passkey: + site.generate_new_passkey() + site.save() + assert site.id + user_in_site = models.Member.objects.filter(user=request.user,site=site) + if not user_in_site: # for edits, might already be! + mbr = site.member_set.create(user=request.user, role='INSTR') mbr.save() - if is_add or (current_access_level != course.access): + if is_add or (current_access_level != site.access): # we need to configure permissions. - return HttpResponseRedirect(course.course_url('edit/permission/')) + return HttpResponseRedirect(site.site_url('edit/permission/')) else: return HttpResponseRedirect('../') # back to main view. # no access-control needed to protect title lookup. -def add_new_course_ajax_title(request): +def add_new_site_ajax_title(request): course_code = request.GET['course_code'] title = models.campus.course_code_lookup_title(course_code) return HttpResponse(simplejson.dumps({'title':title})) @instructors_only -def edit_course_permissions(request, course_id): - course = get_object_or_404(models.Course, pk=course_id) +def edit_site_permissions(request, site_id): + site = get_object_or_404(models.Site, pk=site_id) # choices: make the access-choice labels more personalized than # the ones in 'models'. choices = [ @@ -102,15 +102,15 @@ def edit_course_permissions(request, course_id): choose_access = django.forms.Select(choices=choices) if request.method != 'POST': - return g.render('edit_course_permissions.xhtml', **locals()) + return g.render('edit_site_permissions.xhtml', **locals()) else: POST = request.POST if 'action_change_code' in POST: # update invitation code ------------------------------------- - course.generate_new_passkey() - course.access = u'INVIT' - course.save() + site.generate_new_passkey() + site.access = u'INVIT' + site.save() return HttpResponseRedirect('.#student_access') elif 'action_save_instructor' in POST: @@ -122,9 +122,9 @@ def edit_course_permissions(request, course_id): instr = models.maybe_initialize_user(iname) if instr: try: - return models.Member.objects.get(user=instr, course=course) + return models.Member.objects.get(user=instr, site=site) except models.Member.DoesNotExist: - return models.Member.objects.create(user=instr, course=course) + return models.Member.objects.create(user=instr, site=site) # add a new instructor if iname: @@ -134,7 +134,7 @@ def edit_course_permissions(request, course_id): instr.save() else: instructor_error = 'No such user: %s' % iname - return g.render('edit_course_permissions.xhtml', **locals()) + return g.render('edit_site_permissions.xhtml', **locals()) # removing and changing roles of instructors @@ -144,12 +144,12 @@ def edit_course_permissions(request, course_id): 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 = models.Member.objects.get(pk=instr_id, site=site) 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 = models.Member.objects.get(pk=instr_id, site=site) instr.delete() # todo, should have some error-reporting. return HttpResponseRedirect('.') @@ -157,51 +157,51 @@ def edit_course_permissions(request, course_id): elif 'action_save_student' in POST: # update student details ------------------------------------ access = POST.get('access') - course.access = access + site.access = access # drop all provided users. fixme, this could be optimized to do add/drops. - models.Member.objects.filter(course=course, provided=True).delete() - if course.access == u'STUDT': - initial_sections = course.sections() + models.Member.objects.filter(site=site, provided=True).delete() + if site.access == u'STUDT': + initial_sections = site.sections() # add the 'new section' if any new_sec = request.POST.get('add_section') new_sec = models.section_decode_safe(new_sec) if new_sec: - course.add_sections(new_sec) + site.add_sections(new_sec) # remove the sections to be dropped to_remove = [models.section_decode_safe(name.rsplit('_',1)[1]) \ for name in POST \ if name.startswith('remove_section_')] - course.drop_sections(*to_remove) - student_names = models.campus.students_in(*course.sections()) + site.drop_sections(*to_remove) + student_names = models.campus.students_in(*site.sections()) for name in student_names: user = models.maybe_initialize_user(name) if user: - if not models.Member.objects.filter(course=course, user=user): + if not models.Member.objects.filter(site=site, user=user): mbr = models.Member.objects.create( - course=course, user=user, + site=site, user=user, role='STUDT', provided=True) mbr.save() else: pass - course.save() + site.save() return HttpResponseRedirect('.#student_access') @instructors_only -def delete_course(request, course_id): - course = get_object_or_404(models.Course, pk=course_id) +def delete_site(request, site_id): + site = get_object_or_404(models.Site, pk=site_id) if request.POST.get('confirm_delete'): - course.delete() - return HttpResponseRedirect(reverse('my_courses')) + site.delete() + return HttpResponseRedirect(reverse('my_sites')) else: return HttpResponseRedirect('../') #----------------------------------------------------------------------------- -# Course Invitation Code handler +# Site Invitation Code handler @login_required # must be, to avoid/audit brute force attacks. -def course_invitation(request): +def site_invitation(request): if request.method != 'POST': - return g.render('course_invitation.xhtml', code='', error='', + return g.render('site_invitation.xhtml', code='', error='', **locals()) else: code = request.POST.get('code', '').strip() @@ -210,8 +210,8 @@ def course_invitation(request): return HttpResponseRedirect('.') try: # note, we only allow the passkey if access='INVIT'. - crs = models.ReadingList.objects.filter(access='INVIT').get(passkey=code) - except models.ReadingList.DoesNotExist: + crs = models.Site.objects.filter(access='INVIT').get(passkey=code) + except models.Site.DoesNotExist: # todo, do we need a formal logging system? Or a table for # invitation failures? They should be captured somehow, I # think. Should we temporarily disable accounts after @@ -219,41 +219,41 @@ def course_invitation(request): log('WARN', 'Invitation failure, user %r gave code %r' % \ (request.user.username, code)) error = _('The code you provided is not valid.') - return g.render('course_invitation.xhtml', **locals()) + return g.render('site_invitation.xhtml', **locals()) # the passkey is good; add the user if not already a member. - if not models.Member.objects.filter(user=request.user, course=crs): - mbr = models.Member.objects.create(user=request.user, course=crs, + if not models.Member.objects.filter(user=request.user, site=crs): + mbr = models.Member.objects.create(user=request.user, site=crs, role='STUDT') mbr.save() - return HttpResponseRedirect(crs.course_url()) + return HttpResponseRedirect(crs.site_url()) #----------------------------------------------------------------------------- -# ReadingList-instance handlers +# Site-instance handlers @members_only -def course_detail(request, course_id): - course = get_object_or_404(models.ReadingList, pk=course_id) - return g.render('course_detail.xhtml', course=course) +def site_detail(request, site_id): + site = get_object_or_404(models.Site, pk=site_id) + return g.render('site_detail.xhtml', site=site) @members_only -def course_search(request, course_id): - course = get_object_or_404(models.ReadingList, pk=course_id) - return search(request, in_course=course) +def site_search(request, site_id): + site = get_object_or_404(models.Site, pk=site_id) + return search(request, in_site=site) @login_required -def course_join(request, course_id): - """Self-register into an open-registration course.""" - course = get_object_or_404(models.ReadingList, pk=course_id) - if not course.is_joinable_by(request.user): +def site_join(request, site_id): + """Self-register into an open-registration site.""" + site = get_object_or_404(models.Site, pk=site_id) + if not site.is_joinable_by(request.user): # user should never see this. - return simple_message(_('You cannot join this course.'), - _('Sorry, but you cannot join this course at this time.')) + return simple_message(_('You cannot join this site.'), + _('Sorry, but you cannot join this site at this time.')) elif request.method != 'POST': - return g.render('course_join.xhtml', course=course) + return g.render('site_join.xhtml', site=site) else: - mbr = models.Member.objects.create(user=request.user, course=course, role='STUDT') + mbr = models.Member.objects.create(user=request.user, site=site, role='STUDT') mbr.save() - return HttpResponseRedirect(course.course_url()) + return HttpResponseRedirect(site.site_url()) diff --git a/conifer/templates/browse_index.xhtml b/conifer/templates/browse_index.xhtml index a47de56..dd6fad3 100644 --- a/conifer/templates/browse_index.xhtml +++ b/conifer/templates/browse_index.xhtml @@ -10,7 +10,7 @@ title = _('Browse the Reserves')

${title}

- (Note: some course materials may require you + (Note: some reserve materials may require you to log in)

Choose from one of the options below:

diff --git a/conifer/templates/components/site.xhtml b/conifer/templates/components/site.xhtml index 304b62a..c903692 100644 --- a/conifer/templates/components/site.xhtml +++ b/conifer/templates/components/site.xhtml @@ -1,13 +1,13 @@ -
-
+
-
-
- ${course_search(course)} -
${course.department}
-

${course.code}: ${course.title}

+
+
+ ${site_search(site)} +
${site.department}
+

${site.code}: ${site.title}

@@ -61,7 +61,7 @@ searchtext = _('search this course...') py:with="hier=item.hierarchy()[:-1]; lastnum=len(hier)" class="nestedtitle"> diff --git a/conifer/templates/courses.xhtml b/conifer/templates/courses.xhtml new file mode 100644 index 0000000..7b9c41a --- /dev/null +++ b/conifer/templates/courses.xhtml @@ -0,0 +1,26 @@ + + + + + + ${title} + + + +

${title}

+ + Name + + + ${item.title}, ${item.term} + + ${pagetable(paginator, count, pagerow, pageheader)} + + diff --git a/conifer/templates/edit_site.xhtml b/conifer/templates/edit_site.xhtml index 7f7ec0c..e85e654 100644 --- a/conifer/templates/edit_site.xhtml +++ b/conifer/templates/edit_site.xhtml @@ -1,22 +1,22 @@ - + ${title} - - ${course_banner(course)} + ${site_banner(site)} ${nested_title(parent_item)}

${title}

diff --git a/conifer/templates/item/item_add_elec.xhtml b/conifer/templates/item/item_add_elec.xhtml index 57ef9d6..df23053 100644 --- a/conifer/templates/item/item_add_elec.xhtml +++ b/conifer/templates/item/item_add_elec.xhtml @@ -1,13 +1,13 @@ - + ${title} - ${course_banner(course)} + ${site_banner(site)} ${nested_title(parent_item)}
${offer_to_delete(item)}

${title}

diff --git a/conifer/templates/item/item_add_url.xhtml b/conifer/templates/item/item_add_url.xhtml index ee75605..ad752d7 100644 --- a/conifer/templates/item/item_add_url.xhtml +++ b/conifer/templates/item/item_add_url.xhtml @@ -1,13 +1,13 @@ - + ${title} - - -

${title}

- - Name - - - ${item.title}, ${item.term} - - ${pagetable(paginator, count, pagerow, pageheader)} - - diff --git a/conifer/templates/tabbar.xhtml b/conifer/templates/tabbar.xhtml index 52ffe00..99b2ad8 100644 --- a/conifer/templates/tabbar.xhtml +++ b/conifer/templates/tabbar.xhtml @@ -9,7 +9,7 @@