Add Term Changeover option
authorArt Rhyno <art632000@yahoo.ca>
Thu, 10 Apr 2014 15:49:34 +0000 (11:49 -0400)
committerArt Rhyno <art632000@yahoo.ca>
Thu, 10 Apr 2014 15:49:34 +0000 (11:49 -0400)
Moving courses to a new Term has previously been a process of going
though each course site. This option allows groups of course sites
to be copied over to a new Term all at once.

Signed-off-by: Art Rhyno <art632000@yahoo.ca>
conifer/syrup/views/sites.py
conifer/templates/admin/index.xhtml
conifer/templates/browse_index.xhtml

index 9eac7fe..83cc5a8 100644 (file)
@@ -196,22 +196,118 @@ def my_sites(request):
 def my_tests(request):
     return g.render('my_test.xhtml', **locals())
 
+#add occurence value to sites
+def add_to_sites(sites):
+    term_sites = []
+    i = 0
+    for site in sites:
+        term_sites.append([i,site])
+        i = i + 1
+
+    return term_sites
+
+#get specified terms if provided
+def get_sel_terms(request):
+    start_term = None
+    end_term = None
+
+    if request.method == 'POST':
+       sel_start = int(request.POST['site_start_term'])
+       sel_end = int(request.POST['site_end_term'])
+       if sel_start > 0 and sel_end > 0:
+           start_term = models.Term.objects.get(pk=sel_start)
+           end_term = models.Term.objects.get(pk=sel_end)
+
+    return start_term, end_term
+
+#get ids for selected sites
+def get_sel_sites(request):
+    selected = []
+    if request.method == 'POST':
+       sites_count = int(request.POST['sites_count'])
+       if sites_count > 0:
+           for i in range(sites_count):
+              site_bx = 'site_%d' % i
+              if site_bx in request.POST:
+                 site_sel = request.POST[site_bx]
+                 selected.append(int(site_sel))
+    return selected
+
+#copy sites to new terms
+def duplicate_sites(request,sel_sites,new_start_term,new_end_term):
+    duplicated = []
+    if len(sel_sites) > 0 and new_start_term is not None and new_end_term is not None:
+        for sel in sel_sites:
+            sel_site = models.Site.objects.get(pk=sel)
+            course_site = models.Site.objects.create(
+               course = sel_site.course,
+               start_term = new_start_term,
+               end_term = new_end_term,
+               owner = sel_site.owner,
+               service_desk = sel_site.service_desk)
+            _copy_contents(request, sel_site, course_site)
+            duplicated.append(course_site.pk)
+    return duplicated
+
+#set up query for browse display
+def setup_site_list(browse_option, time_query, dup_list):
+    sites = None
+    blocks = None
+    if browse_option == 'Instructor':
+        if len(dup_list) == 0:
+           sites = list(models.Site.objects.order_by('owner__last_name', 'course__department__name', 'course__code').
+                    select_related().filter(time_query))
+        else:
+           sites = list(models.Site.objects.order_by('owner__last_name', 'course__department__name', 'course__code').
+                    select_related().filter(id__in=dup_list))
+        sites = add_to_sites(sites)
+        blocks = itertools.groupby(sites, lambda s: s[1].owner.last_name)
+    elif browse_option == 'Course':
+        if len(dup_list) == 0:
+           sites = list(models.Site.objects.order_by('course__code', 'owner__last_name', 'course__department__name').
+                    select_related().filter(time_query))
+        else:
+           sites = list(models.Site.objects.order_by('course__code', 'owner__last_name', 'course__department__name').
+                    select_related().filter(id__in=dup_list))
+        sites = add_to_sites(sites)
+        blocks = itertools.groupby(sites, lambda s: s[1].course.code)
+    else:
+        if len(dup_list) == 0:
+            sites = list(models.Site.objects.order_by('course__department__name', 'course__code', 'owner__last_name').
+                    select_related().filter(time_query))
+        else:
+            sites = list(models.Site.objects.order_by('course__department__name', 'course__code', 'owner__last_name').
+                    select_related().filter(id__in=dup_list))
+        sites = add_to_sites(sites)
+        blocks = itertools.groupby(sites, lambda s: s[1].course.department)
+
+    return sites, blocks
+
 def browse(request, browse_option='Department'):
     #the defaults should be moved into a config file or something...
     page_num = int(request.GET.get('page', 1))
     count    = int(request.GET.get('count', 5))
+
+    sel_sites = get_sel_sites(request)
+    start_term, end_term = get_sel_terms(request)
     timeframe = request.session.get('timeframe', 0)
     time_query = models.Term.timeframe_query(timeframe)
+
+    term_sites = []
+    show_terms = 0
     queryset = None
-    if browse_option == 'Instructor':
-        sites = list(models.Site.objects.order_by('owner__last_name', 'course__department__name', 'course__code').select_related().filter(time_query))
-        blocks = itertools.groupby(sites, lambda s: s.owner.last_name)
-    elif browse_option == 'Course':
-        sites = list(models.Site.objects.order_by('course__code', 'owner__last_name', 'course__department__name').select_related().filter(time_query))
-        blocks = itertools.groupby(sites, lambda s: s.course.code)
-    else:
-        sites = list(models.Site.objects.order_by('course__department__name', 'course__code', 'owner__last_name').select_related().filter(time_query))
-        blocks = itertools.groupby(sites, lambda s: s.course.department)
+    if request.method == 'POST':
+        term_sites = duplicate_sites(request,sel_sites,start_term,end_term)
+        
+    sites, blocks = setup_site_list(browse_option, time_query, term_sites)
+
+    if not request.user.is_anonymous():
+        if request.user.can_create_sites() and request.method == 'GET':
+            show_terms = int(request.GET.get('termdup', 0))
+            if show_terms > 0:
+                instance = models.Site()
+                form = NewSiteForm(instance=instance)
     return g.render('browse_index.xhtml', **locals())
 
 
@@ -285,7 +381,7 @@ def _revert_parms(request, source_site):
             if barcode and orig_call and orig_desk and orig_modifier:
                 update_status = opensrf.ils_item_update(barcode, orig_prefix, orig_call,
                                     orig_suffix, orig_modifier, orig_desk)
-                # print "update_status", update_status
+                #print "update_status", update_status
         if update_status:
             for sub in subitems:
                 revert_item(parent, sub)
index 263d679..d68a865 100644 (file)
@@ -22,24 +22,28 @@ title = _('Administrative Options')
     <li><a href="desks/">Service Desks</a></li>
     <li><a href="depts/">Departments</a></li>
     <li><a href="courses/">Courses</a></li>
+    <li><a href="../browse/?termdup=1">Term Changeover</a></li>
     <li><a href="targets/">Z39.50 Targets</a></li>
     <li><a href="config/">Configuration settings</a></li>
-    <!-- <li><a href="targets/">Z39.50 Targets</a></li> -->
   </ul>
-  <!-- <ul> -->
-  <!--   <li><a href="../zsearch/">Search Z39.50 Targets</a></li> -->
-  <!-- </ul> -->
   <ul>
     <li><a href="staff/add/">Add new staff user</a></li>
   </ul>
+  <!--
+    There are some hooks to pulling course information from sakai,
+    uncomment these and examine the files in conifer/integration/sakai_linktool
+    if that is an option at your site.
+  -->
+  <!--
   <ul>
     <li py:if="gethook('department_course_catalogue')">
-      <a href="update_depts_courses">Automatically update departments and courses</a>
+      <a href="update_depts_courses">Automatically update departments and courses (Conifer only)</a>
     </li>
     <li py:if="gethook('term_catalogue')">
-      <a href="update_terms">Automatically update terms</a>
+      <a href="update_terms">Automatically update terms (Conifer only)</a>
     </li>
   </ul>
+  -->
   <ul>
     <li><a href="../djadmin/">Advanced Administration</a></li>
   </ul>
index 0082932..ecb544c 100644 (file)
@@ -7,6 +7,9 @@ if browse_option == 'Instructor':
 elif browse_option == 'Course':
     option2 = _('Department')
     option3 = _('Instructor')
+dup_option = _('Duplicate Courses')
+check_option = _('Check/Uncheck All')
+sites_count = len(sites)
 ?>
 <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:xi="http://www.w3.org/2001/XInclude"
@@ -15,16 +18,44 @@ elif browse_option == 'Course':
 <xi:include href="components/timeframe.xhtml"/>
 <head>
   <title>All Reserves by ${browse_option}</title>
+  <script py:if="show_terms==1" type="text/javascript"> 
+    //toggle selection for top and bottom
+    $(document).ready(function () {
+        $("#checkalltop").click(function () {
+           $(".checkBoxClass").attr('checked', this.checked);
+        });
+    });
+    $(document).ready(function () {
+        $("#checkallbottom").click(function () {
+           $(".checkBoxClass").attr('checked', this.checked);
+        });
+    });
+   </script>
 </head>
 <body>
+  <span py:if="show_terms==0">
   <h1>All Reserves by ${browse_option}</h1> 
     (list by <a href="${ROOT}/browse/${option2}">${option2}</a>, 
     list by <a href="${ROOT}/browse/${option3}">${option3}</a>)
+  </span>
+  <span py:if="show_terms==1">
+  <h1>All Reserves by ${browse_option}</h1> 
+    (list by <a href="${ROOT}/browse/${option2}?termdup=1">${option2}</a>, 
+    list by <a href="${ROOT}/browse/${option3}?termdup=1">${option3}</a>)
+  </span>
   ${timeframe_nav(timeframe)}
   <p py:if="user.is_anonymous() and sites">
     (Note: some reserve materials may require you
     to <a href="${ROOT}${settings.LOGIN_URL}?next=${ROOT}/">log in</a>)
   </p>
+  <span py:if="show_terms==1">
+  <div py:with="nfe=form.non_field_errors()">
+    <ul py:if="nfe" class="errorlist">
+      <li py:for="err in nfe">${err}</li>
+    </ul>
+  </div>
+  </span>
+
   
   <img py:def="lock(condition=True)" 
           py:if="condition"
@@ -35,18 +66,98 @@ elif browse_option == 'Course':
     There are no reserves materials within the selected timeframe.
   </p>
 
+  <span py:if="show_terms==0">
   <div py:for="(dept, ss) in blocks">
        <h2>${dept}</h2>
        <div py:for="site in ss">
-         <span py:if="not site.is_open_to(request.user)" style="float: left;">
+         <span py:if="not site[1].is_open_to(request.user)" style="float: left;">
                ${lock()}
          </span>
          <p style="margin-left: 26px;">
-               
-               <a href="${site.site_url()}">${site}</a>
-      </p>
+               <a href="${site[1].site_url()}">${site[1]}</a>
+          </p>
        </div>
   </div>
+  </span>
+
+  <span py:if="show_terms==1">
+  <form action="." method="POST" id="copy_sites_form">
+    <tr py:def="field_row(field, example=None)">
+      <th>${field.label}</th>
+      <td>
+        <ul py:if="field.errors" class="errorlist">
+          <li py:for="err in field.errors">${err}</li>
+        </ul>
+        ${Markup(field)}
+      </td>
+      <td class="example" py:if="example">e.g., ${example}</td>
+    </tr>
+  <table class="metadata_table">
+  ${field_row(form.start_term)}
+  ${field_row(form.end_term)}
+  </table>
+  <input type="submit" style="font-size: 115%;" name="submit" id="submitButton1" value="${dup_option}" onClick='return formCheck();'> </input>
+  <input type="hidden" name="sites_count" value="${sites_count}"/>
+  <input type="hidden" name="site_start_term" id="site_start_term"/>
+  <input type="hidden" name="site_end_term" id="site_end_term"/>
+  <fieldset>
+  <div><input type="checkbox" id="checkalltop" name="checkalltop" class="checkalltop">${check_option}</input></div>
+  <div py:for="(dept, ss) in blocks">
+       <h2>${dept}</h2>
+       <div py:for="site in ss">
+          <input type="checkbox" class="checkBoxClass" name="site_${site[0]}" value="${site[1].pk}"/>
+         <a href="${site[1].site_url()}">${site[1]}</a>
+       </div>
+  </div>
+  </fieldset>
+  <table id="copy_sites_bottom_section" class="metadata_table">
+  ${field_row(form.start_term)}
+  ${field_row(form.end_term)}
+  </table>
+  <input type="submit" style="font-size: 115%;" name="submit" id="submitButton2" value="${dup_option}" onClick='return formCheck();'> </input>
+  <div><input type="checkbox" id="checkallbottom" name="checkallbottom" class="checkallbottom">${check_option}</input></div>
+  </form>
+  </span>
+
   <div class="gap"/>
+
+  <script py:if="show_terms==1" type="text/javascript"> //<![CDATA[ 
+   //do some checks on term dates and update hidden values for results -
+   //using 2 selection boxes can mess up both django's and jquery's 
+   //form handling and this old school approach gets around the problem
+   function formCheck() {
+       var startTerm = -1;
+       var endTerm = -1;
+       var optionElems = document.getElementsByTagName('option');
+       //churn through all options presented on the page
+       for (var i = 0; i < optionElems.length; i++) {
+           if (optionElems[i].selected) {
+               var parentElemId = optionElems[i].parentNode.id;
+               if (parentElemId && optionElems[i].value && parentElemId.indexOf("start_term") != -1) {
+                      startTerm = parseInt(optionElems[i].value);
+               }
+               if (parentElemId && optionElems[i].value && parentElemId.indexOf("end_term") != -1) {
+                      endTerm = parseInt(optionElems[i].value);
+               }
+           }
+       }
+       //these are the ids of the terms in the database and should never be negative
+       if (startTerm < 0 || endTerm < 0) {
+          alert("Missing Term Values");
+          return false;
+       }
+       //term values can be equal but a course can not end before it starts
+       if (startTerm > endTerm) {
+          alert("Start Term must be less than or equal to End Term");
+          return false;
+       }
+       //update the values to be used in creating the courses
+       var startElem = document.getElementById("site_start_term");
+       startElem.value = startTerm
+       var endElem = document.getElementById("site_end_term");
+       endElem.value = endTerm
+       return true;
+   }
+  // ]]></script>
 </body>
 </html>