Commits

Luke Plant  committed 1fd2dcb Merge

Merged from default

  • Participants
  • Parent commits b1d1425, 1a3fd37
  • Branches live

Comments (0)

Files changed (6)

File cciw/officers/views.py

 from cciw.officers.references import reference_form_info
 from cciw.utils.views import close_window_response
 from securedownload.views import access_folder_securely
-import smtplib
 
 
 def _copy_application(application):
     return render(request, template_name, c)
 
 
-def email_sending_failed_response():
-    return HttpResponse("""<p>E-mail failed to send.  This is likely a temporary
-    error, please press back in your browser and try again.</p>""")
-
-
 class SetEmailForm(forms.Form):
     email = forms.EmailField(widget=forms.TextInput(attrs={'size':'50'}))
 
         if 'send' in request.POST:
             messageform = SendReferenceRequestForm(request.POST, message_info=messageform_info)
             if messageform.is_valid():
-                try:
-                    send_reference_request_email(wordwrap(messageform.cleaned_data['message'], 70), ref)
-                except smtplib.SMTPException:
-                    return email_sending_failed_response()
+                send_reference_request_email(wordwrap(messageform.cleaned_data['message'], 70), ref)
                 ref.requested = True
                 ref.log_request_made(request.user, datetime.datetime.now())
                 ref.save()
     year = int(year)
     # We need a lot of information. Try to get it in a few up-front queries
     camps = list(Camp.objects.filter(year=year).order_by('number'))
+    # Selected camps:
+    # We need to support URLs that indicate which camp to select, so we
+    # can permalink nicely.
+    selected_camp_numbers = None
+    if 'camp' in request.GET:
+        try:
+            selected_camp_numbers = set(map(int, request.GET.getlist('camp')))
+        except ValueError:
+            pass
+    if not selected_camp_numbers: # empty or None
+        # Assume all, because having none is never useful
+        selected_camp_numbers = set([c.number for c in camps])
+
+    # We need all the officers, and we need to know which camp(s) they belong
+    # to. Even if we have only selected one camp, it might be nice to know if
+    # they are on other camps. So we get data for all camps, and filter later.
+    # We also want to be able to filtering by javascript in the frontend.
     camps_officers = [[i.officer for i in c.invitation_set.all()] for c in camps]
     all_officers = reduce(operator.or_, map(set, camps_officers))
     all_officers = sorted(all_officers, key=lambda o: (o.first_name, o.last_name))
     for o in all_officers:
         o.temp = {}
         officer_camps = []
+        selected = False
         for c in camps:
             if o.id in officer_ids[c.id]:
                 officer_camps.append(c)
+                if c.number in selected_camp_numbers:
+                    selected = True
         app = officer_apps.get(o.id, None)
         o.temp['camps'] = officer_camps
+        o.temp['selected'] = selected
         o.temp['has_application_form'] = app is not None
         o.temp['application_id'] = app.id if app is not None else None
         o.temp['has_crb'] = o.id in all_crb_officer_ids
         o.temp['crb_check_consent'] = app.crb_check_consent if app is not None else False
 
     c = {'all_officers': all_officers,
+         'camps': camps,
+         'selected_camps': selected_camp_numbers,
          'year':year}
     return render(request, 'cciw/officers/manage_crbs.html', c)
 

File templates/cciw/officers/manage_applications.html

 {% extends "cciw/officers/base.html" %}
 {% load url from future %}
-{% block title %}Manage applications | CCIW Officers{% endblock %}
+{% block title %}Manage applications {{ camp.year }}-{{ camp.number }} | CCIW Officers{% endblock %}
 {% block content %}<div id="content-main">
 <h1>Manage applications</h1>
+<h2>For camp {{ camp }}</h2>
 
 <p>This page allows you to view/download submitted applications in
   different formats. Normally the leaders of the camps (and any

File templates/cciw/officers/manage_crbs.html

 {% extends "cciw/officers/base.html" %}
 {% load url from future %}
+{% block title %}Manage CRBs {{ year }} | CCIW Officers{% endblock %}
 {% block content %}
 <script type="text/javascript">
 function CRBFormSent(officerId) {
                 '_blank',"toolbar=yes,height=600,width=900,location=yes,menubar=yes,scrollbars=yes,resizable=yes");
 
 }
+
+$(document).ready(function() {
+
+    // convert 'data-camps' into jQuery data
+    $('#id_officer_table tbody tr').each(function(idx, elem) {
+        $(elem).data('camps', $(elem).attr('data-camps').split(','));
+    });
+
+    // Handler for camp checkboxes
+    function selectedCampsChanged(ev) {
+        $('#id_campselector input[type=submit]').removeAttr('disabled');
+        var selectedCamps = []
+        $('#id_campselector input[type=checkbox]:checked').each(function(idx, elem) {
+            selectedCamps.push($(elem).val());
+        });
+        // For locating selected camps, we use a comma delimited string
+        // to make it easier to match by using string matching.
+        var campMatch = "," + selectedCamps.join(",") + ",";
+
+        // Now go through all rows
+        $('#id_officer_table tbody tr').each(function(idx, elem) {
+            var show = false;
+            var tr = $(elem);
+            $.each(tr.data('camps'), function(idx, val) {
+                if (campMatch.indexOf(',' + val + ',') != -1) {
+                    show = true;
+                    return false;
+                }
+            });
+            if (show) {
+                tr.show();
+            } else {
+                tr.hide();
+            }
+        });
+    }
+
+    // Add event handler
+    $('#id_campselector input[type=checkbox]').bind('change', selectedCampsChanged);
+
+    // Change the caption on 'update' box, because it is now only useful for
+    // updating the URL, as other updates happen immediately.
+    $('#id_campselector input[type=submit]').attr('disabled', 'disabled').val('Update page address');
+
+});
 </script>
 
 <h1>Manage CRBs</h1>
 <p>To enter information for CRBs that have been <em>completed</em>, use the
  <a href="{% url 'admin:officers_crbapplication_changelist' %}" rel="external">CRB Disclosures admin</a>.</p>
 
-<table>
+<div id='id_campselector'>
+<form action="." method="GET">
+<p>Select camps: {% for camp in camps %}
+<label><input type="checkbox" name="camp" value="{{ camp.number }}"
+{% if camp.number in selected_camps %}checked{% endif %}> {{ camp.number }}</label>&nbsp;&nbsp;
+{% endfor %} <input type="submit" value="Update page">
+</p>
+</form>
+</div>
+
+<table id="id_officer_table">
   <thead>
     <tr>
       <th>Name</th>
   </thead>
   <tbody>
     {% for officer in all_officers %}
-      <tr id="id_highlightdiv_{{ officer.id }}" {% if not officer.temp.has_valid_crb and officer.temp.has_application_form and not officer.temp.last_crb_form_sent %}class="actionable"{% endif %}>
+      <tr id="id_highlightdiv_{{ officer.id }}"
+          {% if not officer.temp.has_valid_crb and officer.temp.has_application_form and not officer.temp.last_crb_form_sent %}class="actionable"{% endif %}
+          data-camps="{% for camp in officer.temp.camps %}{{ camp.number }}{% if not forloop.last %},{% endif %}{% endfor %}"
+          {% if not officer.temp.selected %}style="display: none;"{% endif %}
+>
         <td>{{ officer.first_name }} {{ officer.last_name }}</td>
         <td>{% for camp in officer.temp.camps %}
               <a href="{% url 'cciw.officers.views.officer_list' year=camp.year number=camp.number %}" rel="external">{{ camp.number }}</a>{% if not forloop.last %}, {% endif %}

File templates/cciw/officers/manage_references.html

 {% extends "cciw/officers/base.html" %}
 {% load reference_utils %}
 {% load url from future %}
-{% block title %}Manage references | CCIW Officers{% endblock %}
+{% block title %}Manage references {{ camp.year }}-{{ camp.number }} | CCIW Officers{% endblock %}
 {% block extrastyle %}{{ block.super }}
 <script type="text/javascript">
 //<![CDATA[

File templates/cciw/officers/officer_list.html

 {% extends "cciw/officers/base.html" %}
 {% load url from future %}
 {% load adminmedia %}
-{% block title %}Officer list | CCIW Officers{% endblock %}
+{% block title %}Officer list {{ camp.year }}-{{ camp.number }} | CCIW Officers{% endblock %}
 
 {% block extrastyle %}{{ block.super }}
 <link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />
 {% block bodyclass%}change-form{% endblock %}
 
 {% block content %}<div id="content-main">
-<h1>Officer list - {{ camp }}</h1>
+<h1>Officer list</h1>
+<h2>For camp {{ camp }}</h2>
 
 <p>This page can be used for viewing and managing the officers on your list,
  and for viewing those who have not yet filled in an application form.</p>

File templates/cciw/officers/stats.html

     var officer_list_data = {{ stat.officer_list_data|jsonify }};
     $.plot(placeholder_id,
            [
-            {label: "Officer list",
+            {label: "<a href='{% url "cciw.officers.views.officer_list" year=stat.camp.year number=stat.camp.number %}' target='_blank'>Officer list</a>",
              data: officer_list_data},
-            {label: "Any CRBs",
+            {label: "<a href='{% url "cciw.officers.views.manage_crbs" year=year %}?camp={{ stat.camp.number }}' target='_blank'>Any CRBs</a>",
              data: all_crb_dates_data},
             {label: "Up-to-date CRBs",
              data: valid_crb_dates_data},
-            {label: "Application forms",
+            {label: "<a href='{% url "cciw.officers.views.manage_applications" year=stat.camp.year number=stat.camp.number %}' target='_blank'>Applications</a>",
              data: app_dates_data},
-            {label: "References \u00F7 2",
+            {label: "<a href='{% url "cciw.officers.views.manage_references" year=stat.camp.year number=stat.camp.number %}' target='_blank'>References</a> \u00F7 2",
              data: ref_dates_data}
            ],
            { xaxis: { mode: "time",
                 $("#tooltip").remove();
                 var d = new Date(item.datapoint[0]);
                 var num = item.datapoint[1];
-                var label = item.series.label;
+                var label = $('<div>' + item.series.label + '</div>').text();
                 var stat = num.toFixed(0);
-                if (item.series.label == "References \u00F7 2") {
+                if (item.series.label.match(/References/)) {
                     label = "References";
                     stat = (num * 2).toFixed(0);
                 }