Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[Fix bug 747421] Add temp page for MozCamp LATAM.

- Adds a temporary view, template, and route at /mozcamp.
- Adds a temporary setting, KEYNOTE_FILE, IT will need to set.
- Revert me soon!
  • Loading branch information...
commit aa4a5b9731ddbd03f071378bd220522c519a5070 2 parents 0c2427c + 508dd65
authored April 20, 2012
8  apps/groups/templates/groups/group.html
@@ -72,7 +72,13 @@ <h1 class="span12">Users in Group "{{ name }}"</h1>
72 72
           <img class="profile-photo" src="{{ group.steward.photo_url() }}" alt="{{ _('Profile Photo') }}">
73 73
         </div>
74 74
         <ul>
75  
-          <li><span>{{ group.steward.display_name }}</span></li>
  75
+          <li>
  76
+            <span>
  77
+              <a href="{{ url('profile', group.steward.user.username) }}">
  78
+                {{ group.steward.display_name }}
  79
+              </a>
  80
+            </span>
  81
+          </li>
76 82
           <li>
77 83
             <a href="mailto:{{ group.steward.user.email }}">
78 84
               {{ group.steward.user.email }}
7  apps/phonebook/forms.py
@@ -20,9 +20,12 @@
20 20
 
21 21
 
22 22
 class SearchForm(happyforms.Form):
23  
-    q = forms.CharField(widget=forms.HiddenInput, required=True)
  23
+    q = forms.CharField(widget=forms.HiddenInput, required=False)
24 24
     limit = forms.CharField(widget=forms.HiddenInput, required=False)
25  
-    nonvouched_only = forms.BooleanField(required=False)
  25
+    nonvouched_only = forms.BooleanField(label=_lazy(u'Non Vouched Only'),
  26
+                                         required=False)
  27
+    picture_only = forms.BooleanField(label=_lazy(u'Only users with photos'),
  28
+                                      required=False)
26 29
 
27 30
     def clean_limit(self):
28 31
         """Validate that this limit is numeric and greater than 1"""
31  apps/phonebook/templates/phonebook/keynote.html
... ...
@@ -0,0 +1,31 @@
  1
+{% extends "base.html" %}
  2
+
  3
+{% block page_title %}{{ _('MozCamp LATAM: Keynote') }}{% endblock %}
  4
+{% block body_classes %}box-content{% endblock %}
  5
+
  6
+{% block page_js %}
  7
+  <script type='text/javascript' src='http://videos.mozilla.org/serv/air_mozilla/jwplayer.js'></script>
  8
+  <script>
  9
+    jwplayer('player').setup({
  10
+      'flashplayer': 'http://videos.mozilla.org/serv/air_mozilla/player.swf',
  11
+      'file': '{{ settings.KEYNOTE_FILE }}',
  12
+      'provider': 'rtmp',
  13
+      'streamer': 'rtmp://fml.1237.edgecastcdn.net/201237/',
  14
+      'rtmp.subscribe': 'true',
  15
+      'controlbar': 'over',
  16
+      'playlist': 'none',
  17
+      'dock': 'true',
  18
+      'icons': 'true',
  19
+      'quality': 'true',
  20
+      'autostart': 'true',
  21
+      'width': '620',
  22
+      'height': '350'
  23
+    });
  24
+  </script>
  25
+{% endblock %}
  26
+
  27
+{% block main_content %}
  28
+  <div style="margin: 30px auto; width: 620px;">
  29
+    <div id="player">Do not adjust your television...</div>
  30
+  </div>
  31
+{% endblock %}
14  apps/phonebook/templates/phonebook/search.html
@@ -25,8 +25,22 @@
25 25
         value="{% if form.cleaned_data %}{{ form.cleaned_data.q }}{% endif %}">
26 26
       <input type="hidden" name="limit" id="limit" value="{{ limit }}">
27 27
       <button type="submit" class="btn primary">
  28
+        <span class="icon-search"></span>
28 29
         {{ _('Search') }}
29 30
       </button>
  31
+      <button type="button" id="advanced" class="btn primary">
  32
+        <span class="icon-chevron-down"></span>
  33
+        {{ _('Advanced Options') }}
  34
+      </button>
  35
+      <div class="search-options">
  36
+        {% for f in ['nonvouched_only', 'picture_only'] %}
  37
+          <div id="{{ form[f].name }}-container"
  38
+               class="field {{ form[f].field.widget.attrs['class'] }}">
  39
+            {{ form[f] }}
  40
+            {{ form[f].label_tag() }}
  41
+          </div>
  42
+        {% endfor %}
  43
+      </div>
30 44
     </form>
31 45
     <div class="well">
32 46
       {% if not form.cleaned_data %}
152  apps/phonebook/tests/test_search.py
... ...
@@ -0,0 +1,152 @@
  1
+import os
  2
+
  3
+from django.conf import settings
  4
+
  5
+from nose.tools import eq_
  6
+from pyquery import PyQuery as pq
  7
+
  8
+from common.tests import ESTestCase
  9
+from elasticutils import get_es
  10
+from funfactory.urlresolvers import reverse
  11
+
  12
+from users.models import UserProfile
  13
+
  14
+
  15
+class TestSearch(ESTestCase):
  16
+    def test_search_with_space(self):
  17
+        """Extra spaces should not impact search queries."""
  18
+        amanda = 'Amanda Younger'
  19
+        amandeep = 'Amandeep McIlrath'
  20
+        url = reverse('search')
  21
+        r = self.mozillian_client.get(url, dict(q='Am'))
  22
+        rs = self.mozillian_client.get(url, dict(q=' Am'))
  23
+
  24
+        eq_(r.status_code, 200)
  25
+        peeps = r.context['people']
  26
+        peeps_ws = rs.context['people']
  27
+        saw_amanda = saw_amandeep = False
  28
+
  29
+        for person in peeps:
  30
+            if person.display_name == amanda:
  31
+                saw_amanda = True
  32
+            elif person.display_name == amandeep:
  33
+                saw_amandeep = True
  34
+            if saw_amanda and saw_amandeep:
  35
+                break
  36
+
  37
+        assert peeps[0].id in (peeps_ws[0].id, peeps_ws[1].id)
  38
+        self.assertTrue(saw_amanda, 'We see first person')
  39
+        self.assertTrue(saw_amandeep, 'We see another person')
  40
+
  41
+    def test_nonvouched_search(self):
  42
+        """Make sure that only non vouched users are returned on search."""
  43
+        amanda = 'Amanda Younger'
  44
+        amandeep = 'Amandeep McIlrath'
  45
+        url = reverse('search')
  46
+        r = self.mozillian_client.get(url, dict(q='Am'))
  47
+        rnv = self.mozillian_client.get(url, dict(q='Am', nonvouched_only=1))
  48
+
  49
+        eq_(r.status_code, 200)
  50
+        peeps = r.context['people']
  51
+        peeps_nv = rnv.context['people']
  52
+
  53
+        saw_amanda = saw_amandeep = False
  54
+
  55
+        for person in peeps:
  56
+            if person.display_name == amandeep:
  57
+                assert person.is_vouched, 'Amanda is a Mozillian'
  58
+                saw_amandeep = True
  59
+            elif person.display_name == amanda:
  60
+                if person.is_vouched:
  61
+                    self.fail('Amandeep should have pending status')
  62
+                saw_amanda = True
  63
+            if saw_amanda and saw_amandeep:
  64
+                break
  65
+
  66
+        self.assertEqual(peeps_nv[0].display_name, amanda)
  67
+        self.assertTrue(saw_amanda, 'We see vouched users')
  68
+        self.assertTrue(saw_amandeep, 'We see non-vouched users')
  69
+        assert all(not person.is_vouched for person in peeps_nv)
  70
+
  71
+    def test_profilepic_search(self):
  72
+        """Make sure searching for only users with profile pics works."""
  73
+        with open(os.path.join(os.path.dirname(__file__), 'profile-photo.jpg')) as f:
  74
+            r = self.mozillian_client.post(reverse('profile.edit'),
  75
+                dict(first_name='Aman', last_name='Withapic', photo=f))
  76
+
  77
+        if not settings.ES_DISABLED:
  78
+            get_es().refresh(settings.ES_INDEXES['default'], timesleep=0)
  79
+
  80
+        amanhasapic = 'Aman Withapic'
  81
+        amanda = 'Amanda Younger'
  82
+        url = reverse('search')
  83
+        r = self.mozillian_client.get(url, dict(q='Am'))
  84
+        rpp = self.mozillian_client.get(url, dict(q='Am', picture_only=1))
  85
+
  86
+        eq_(r.status_code, 200)
  87
+        peeps = r.context['people']
  88
+        peeps_pp = rpp.context['people']
  89
+        saw_amanda = False
  90
+
  91
+        # Make sure that every body has a profile picture
  92
+        for person in peeps:
  93
+            if person.display_name == amanda:
  94
+                if bool(person.photo):
  95
+                    self.fail('Amanda doesnt have a profile pic')
  96
+                saw_amanda = True
  97
+
  98
+        # Make sure amanda shows up in peeps
  99
+        assert amanda in [p.display_name for p in peeps]
  100
+        # Make sure she doesn't show up in peeps_pp
  101
+        assert amanda not in [p.display_name for p in peeps_pp]
  102
+        self.assertEqual(peeps_pp[0].display_name, amanhasapic)
  103
+        self.assertTrue(saw_amanda, 'We dont see profile picture')
  104
+
  105
+    def test_mozillian_search_pagination(self):
  106
+        """Tests the pagination on search.
  107
+
  108
+        1. assumes no page is passed, but valid limit is passed
  109
+        2. assumes invalid page is passed, no limit is passed
  110
+        3. assumes valid page is passed, no limit is passed
  111
+        4. assumes valid page is passed, valid limit is passed
  112
+        """
  113
+        url = reverse('search')
  114
+        r = self.mozillian_client.get(url, dict(q='Amand', limit='1'))
  115
+        peeps = r.context['people']
  116
+        self.assertEqual(len(peeps), 1)
  117
+
  118
+        r = self.mozillian_client.get(url, dict(q='Amand', page='test'))
  119
+        peeps = r.context['people']
  120
+        self.assertEqual(len(peeps), 2)
  121
+
  122
+        r = self.mozillian_client.get(url, dict(q='Amand', page='1'))
  123
+        peeps = r.context['people']
  124
+        self.assertEqual(len(peeps), 2)
  125
+
  126
+        r = self.mozillian_client.get(url, dict(q='Amand', page='test',
  127
+                                                limit='1'))
  128
+        peeps = r.context['people']
  129
+        self.assertEqual(len(peeps), 1)
  130
+
  131
+        r = self.mozillian_client.get(url, dict(q='Amand', page='test',
  132
+                                                limit='x'))
  133
+        peeps = r.context['people']
  134
+        self.assertEqual(len(peeps), 2)
  135
+
  136
+        r = self.mozillian_client.get(url, dict(q='Amand', page='test',
  137
+                                                limit='-3'))
  138
+        peeps = r.context['people']
  139
+        self.assertEqual(len(peeps), 2)
  140
+
  141
+    def test_empty_query_search(self):
  142
+        """Make sure the search method works with an empty query"""
  143
+        assert UserProfile.search('').count()
  144
+
  145
+    def test_proper_url_arg_handling(self):
  146
+        search_url = reverse('search')
  147
+        r = self.mozillian_client.get(search_url)
  148
+        assert not pq(r.content)('.result')
  149
+
  150
+        r = self.mozillian_client.get(search_url,
  151
+                                      dict(q=u'', nonvouched_only=1))
  152
+        assert pq(r.content)('.result')
74  apps/phonebook/tests/test_views.py
@@ -8,7 +8,7 @@
8 8
 from nose.tools import eq_
9 9
 from pyquery import PyQuery as pq
10 10
 
11  
-from common.tests import TestCase, ESTestCase
  11
+from common.tests import TestCase
12 12
 from funfactory.urlresolvers import set_url_prefix, reverse
13 13
 
14 14
 
@@ -333,78 +333,6 @@ def test_localized_search_plugin(self):
333 333
         assert '/fr/search' in response.content
334 334
 
335 335
 
336  
-class TestSearch(ESTestCase):
337  
-    def test_mozillian_search(self):
338  
-        """Test our search."""
339  
-        amanda = 'Amanda Younger'
340  
-        amandeep = 'Amandeep McIlrath'
341  
-        url = reverse('search')
342  
-        r = self.mozillian_client.get(url, dict(q='Am'))
343  
-        rs = self.mozillian_client.get(url, dict(q=' Am'))
344  
-        rnv = self.mozillian_client.get(url, dict(q='Am', nonvouched_only=1))
345  
-
346  
-        eq_(r.status_code, 200)
347  
-        peeps = r.context['people']
348  
-        peeps_ws = rs.context['people']
349  
-        peeps_nv = rnv.context['people']
350  
-
351  
-        saw_amandeep = saw_amanda = False
352  
-
353  
-        for person in peeps:
354  
-            if person.display_name == amandeep:
355  
-                assert person.is_vouched, 'Amandeep is a Mozillian'
356  
-                saw_amandeep = True
357  
-            elif person.display_name == amanda:
358  
-                if person.is_vouched:
359  
-                    self.fail('Amanda is pending status')
360  
-                saw_amanda = True
361  
-            if saw_amandeep and saw_amanda:
362  
-                break
363  
-
364  
-        assert peeps[0].id in (peeps_ws[0].id, peeps_ws[1].id)
365  
-        self.assertEqual(peeps_nv[0].display_name, amanda)
366  
-        self.assertTrue(saw_amandeep, 'We see Mozillians')
367  
-        self.assertTrue(saw_amanda, 'We see Pending')
368  
-
369  
-        assert all(not person.is_vouched for person in peeps_nv)
370  
-
371  
-    def test_mozillian_search_pagination(self):
372  
-        """Tests the pagination on search.
373  
-
374  
-        1. assumes no page is passed, but valid limit is passed
375  
-        2. assumes invalid page is passed, no limit is passed
376  
-        3. assumes valid page is passed, no limit is passed
377  
-        4. assumes valid page is passed, valid limit is passed
378  
-        """
379  
-        url = reverse('search')
380  
-        r = self.mozillian_client.get(url, dict(q='Amand', limit='1'))
381  
-        peeps = r.context['people']
382  
-        self.assertEqual(len(peeps), 1)
383  
-
384  
-        r = self.mozillian_client.get(url, dict(q='Amand', page='test'))
385  
-        peeps = r.context['people']
386  
-        self.assertEqual(len(peeps), 2)
387  
-
388  
-        r = self.mozillian_client.get(url, dict(q='Amand', page='1'))
389  
-        peeps = r.context['people']
390  
-        self.assertEqual(len(peeps), 2)
391  
-
392  
-        r = self.mozillian_client.get(url, dict(q='Amand', page='test',
393  
-                                                limit='1'))
394  
-        peeps = r.context['people']
395  
-        self.assertEqual(len(peeps), 1)
396  
-
397  
-        r = self.mozillian_client.get(url, dict(q='Amand', page='test',
398  
-                                                limit='x'))
399  
-        peeps = r.context['people']
400  
-        self.assertEqual(len(peeps), 2)
401  
-
402  
-        r = self.mozillian_client.get(url, dict(q='Amand', page='test',
403  
-                                                limit='-3'))
404  
-        peeps = r.context['people']
405  
-        self.assertEqual(len(peeps), 2)
406  
-
407  
-
408 336
 def _logged_in_html(response):
409 337
     doc = pq(response.content)
410 338
     return doc('a#logout')
1  apps/phonebook/urls.py
@@ -19,6 +19,7 @@
19 19
     url('^opensearch.xml$', views.search_plugin, name='search_plugin'),
20 20
     url('^search$', views.search, name='search'),
21 21
     url('^vouch$', views.vouch, name='vouch'),
  22
+    url('^mozcamp$', views.keynote, name='keynote'),
22 23
 
23 24
     url('^invite$', views.invite, name='invite'),
24 25
     url('^invited/(?P<id>\d+)$', views.invited, name='invited'),
37  apps/phonebook/views.py
@@ -8,7 +8,7 @@
8 8
 from django.http import HttpResponseRedirect, HttpResponseForbidden
9 9
 from django.shortcuts import redirect, render
10 10
 from django.views.decorators.cache import cache_page, never_cache
11  
-from django.views.decorators.http import require_POST
  11
+from django.views.decorators.http import require_POST, require_GET
12 12
 
13 13
 import commonware.log
14 14
 from funfactory.urlresolvers import reverse
@@ -136,35 +136,40 @@ def search(request):
136 136
     num_pages = 0
137 137
     limit = None
138 138
     nonvouched_only = False
  139
+    picture_only = False
139 140
     people = []
140 141
     show_pagination = False
141 142
     form = forms.SearchForm(request.GET)
142 143
 
143 144
     if form.is_valid():
144  
-        query = form.cleaned_data.get('q', '')
  145
+        query = form.cleaned_data.get('q', u'')
145 146
         limit = form.cleaned_data['limit']
146 147
         vouched = False if form.cleaned_data['nonvouched_only'] else None
  148
+        profilepic = True if form.cleaned_data['picture_only'] else None
147 149
         page = request.GET.get('page', 1)
148 150
 
149  
-        profiles = UserProfile.search(query, vouched=vouched)
  151
+        # If nothing has been entered don't load any searches.
  152
+        if not (not query and vouched is None and profilepic is None):
  153
+            profiles = UserProfile.search(query, vouched=vouched, photo=profilepic)
150 154
 
151  
-        paginator = Paginator(profiles, limit)
  155
+            paginator = Paginator(profiles, limit)
152 156
 
153  
-        try:
154  
-            people = paginator.page(page)
155  
-        except PageNotAnInteger:
156  
-            people = paginator.page(1)
157  
-        except EmptyPage:
158  
-            people = paginator.page(paginator.num_pages)
  157
+            try:
  158
+                people = paginator.page(page)
  159
+            except PageNotAnInteger:
  160
+                people = paginator.page(1)
  161
+            except EmptyPage:
  162
+                people = paginator.page(paginator.num_pages)
159 163
 
160  
-        if paginator.count > forms.PAGINATION_LIMIT:
161  
-            show_pagination = True
162  
-            num_pages = len(people.paginator.page_range)
  164
+            if paginator.count > forms.PAGINATION_LIMIT:
  165
+                show_pagination = True
  166
+                num_pages = len(people.paginator.page_range)
163 167
 
164 168
     d = dict(people=people,
165 169
              form=form,
166 170
              limit=limit,
167 171
              nonvouched_only=nonvouched_only,
  172
+             picture_only=picture_only,
168 173
              show_pagination=show_pagination,
169 174
              num_pages=num_pages)
170 175
 
@@ -221,3 +226,9 @@ def vouch(request):
221 226
         return redirect(reverse('profile', args=[p.user.username]))
222 227
 
223 228
     return HttpResponseForbidden
  229
+
  230
+
  231
+@require_GET
  232
+@vouch_required
  233
+def keynote(request):
  234
+    return render(request, 'phonebook/keynote.html')
18  apps/users/models.py
@@ -152,23 +152,29 @@ def fields(self):
152 152
         attrs = ('username', 'first_name', 'last_name', 'email', 'last_login',
153 153
                  'date_joined')
154 154
         d.update(dict((a, getattr(self.user, a)) for a in attrs))
155  
-        # Index group ids... for fun.
156  
-        groups = list(self.groups.values_list('name', flat=True))
157  
-        d.update(dict(groups=groups))
  155
+        d.update(dict(has_photo=bool(self.photo)))
  156
+        # Index groups and skills ... for fun.
  157
+        d.update(dict(groups=list(self.groups.values_list('name', flat=True))))
158 158
         return d
159 159
 
160 160
     @classmethod
161  
-    def search(cls, query, vouched=None):
  161
+    def search(cls, query, vouched=None, photo=None):
162 162
         """Sensible default search for UserProfiles."""
163 163
         query = query.lower().strip()
164 164
         fields = ('first_name__text', 'last_name__text', 'display_name__text',
165 165
                   'username__text', 'bio__text', 'website__text',
166 166
                   'email__text', 'groups__text', 'first_name__startswith',
167 167
                   'last_name__startswith', 'ircname')
168  
-        q = dict((field, query) for field in fields)
169  
-        s = S(cls).query(or_=q)
  168
+        if query:
  169
+            q = dict((field, query) for field in fields)
  170
+            s = S(cls).query(or_=q)
  171
+        else:
  172
+            s = S(cls)
  173
+
170 174
         if vouched is not None:
171 175
             s = s.filter(is_vouched=vouched)
  176
+        if photo is not None:
  177
+            s = s.filter(has_photo=photo)
172 178
         return s
173 179
 
174 180
 
2  apps/users/views.py
@@ -84,8 +84,6 @@ def register(request):
84 84
             messages.info(request, _(u'Your account has been created.'))
85 85
             return redirect('profile', user.username)
86 86
 
87  
-    # When changing this keep in mind that the same view is used for
88  
-    # phonebook.edit_profile.
89 87
     # 'user' object must be passed in because we are not logged in
90 88
     return render(request, 'registration/register.html',
91 89
                   dict(form=form,
30  bin/jenkins.sh
@@ -14,15 +14,18 @@ echo "Starting build on executor $EXECUTOR_NUMBER..."
14 14
 # Make sure there's no old pyc files around.
15 15
 find . -name '*.pyc' -exec rm {} \;
16 16
 
17  
-echo "Making Virtualenv"
18  
-virtualenv $VENV --no-site-packages
  17
+
  18
+if [ ! -d "$VENV" ]; then
  19
+    echo "Making virtualenv..."
  20
+    virtualenv $VENV --no-site-packages
  21
+    pip install --upgrade pip
  22
+fi
19 23
 source $VENV/bin/activate
20  
-pip install --upgrade pip
21 24
 pip install coverage
22  
-pip install PyQuery
23  
-pip install mock
  25
+pip install -r requirements/compiled.txt
  26
+pip install -r requirements/dev.txt
24 27
 
25  
-git submodule sync -q
  28
+git submodule sync
26 29
 git submodule update --init --recursive
27 30
 
28 31
 if [ ! -d "$WORKSPACE/vendor" ]; then
@@ -30,10 +33,6 @@ if [ ! -d "$WORKSPACE/vendor" ]; then
30 33
     exit 1
31 34
 fi
32 35
 
33  
-source $VENV/bin/activate
34  
-# pip install -q -r requirements/compiled.txt
35  
-# pip install -q -r requirements/dev.txt
36  
-
37 36
 cat > settings/local.py <<SETTINGS
38 37
 import logging
39 38
 from settings import *
@@ -87,7 +86,7 @@ DEBUG = TEMPLATE_DEBUG = True
87 86
 # ElasticSearch
88 87
 ES_DISABLED = False
89 88
 ES_HOSTS = ['127.0.0.1:9200']
90  
-ES_INDEXES = dict(default='mozillians_dev')
  89
+ES_INDEXES = dict(default='test_${JOB_NAME}')
91 90
 SETTINGS
92 91
 
93 92
 echo "Creating database if we need it..."
@@ -97,7 +96,12 @@ echo "Database name: ${JOB_NAME}"
97 96
 
98 97
 echo "Starting tests..."
99 98
 export FORCE_DB=1
100  
-coverage run manage.py test --noinput --with-xunit
101  
-coverage xml $(find apps lib -name '*.py')
  99
+
  100
+if [ -z $COVERAGE ]; then
  101
+    python manage.py test --noinput --with-xunit --logging-clear-handlers
  102
+else
  103
+    coverage run --omit='*migrations*' manage.py test --noinput --with-xunit --logging-clear-handlers
  104
+    coverage xml --omit='*migrations*' $(find apps lib -name '*.py')
  105
+fi
102 106
 
103 107
 echo "FIN"
35  media/css/base.css
@@ -30,6 +30,23 @@ body {
30 30
     font:16px/24px Georgia, serif;
31 31
 }
32 32
 
  33
+.skip{
  34
+	left:-999em;
  35
+	position:absolute;
  36
+}
  37
+
  38
+.skip:focus{
  39
+	background:rgb(255,255,255);
  40
+	color:rgb(44,44,44);
  41
+	height:35px;
  42
+	left:0;
  43
+	padding-top:5px;
  44
+	right:0;
  45
+	text-align:center;
  46
+	top:0;
  47
+	z-index:1031; /* One more than .nav-bar-fixed-top */
  48
+}
  49
+
33 50
 .huge,.large,h1,h2,h3,h4 {
34 51
     font-family:OpenSans, "Lucida Sans", "Lucida Grande", "Lucida Sans Unicode", Verdana, sans-serif;
35 52
     font-weight:400;
@@ -72,6 +89,10 @@ h4 {
72 89
     line-height:100%;
73 90
 }
74 91
 
  92
+footer p, #main p { 
  93
+    font-family: 'Open Sans',sans-serif;
  94
+}
  95
+
75 96
 .small,small {
76 97
     font-size:12px;
77 98
     line-height:100%;
@@ -422,6 +443,20 @@ legend {
422 443
     margin-bottom:15px;
423 444
 }
424 445
 
  446
+.search-options {
  447
+    display: none;
  448
+}
  449
+
  450
+.search-options input, .search-options span {
  451
+    display: block;
  452
+    float: left;
  453
+}
  454
+
  455
+.search-options input {
  456
+    margin-left: 40px;
  457
+    margin-right: 10px;
  458
+}
  459
+
425 460
 .edit-profile {
426 461
     max-width: 700px;
427 462
 }
5  media/js/expand.js
... ...
@@ -0,0 +1,5 @@
  1
+$(function(){
  2
+    $('#advanced').click(function(){
  3
+        $('.search-options').slideToggle('fast');
  4
+    });
  5
+});
1  requirements/dev.txt
@@ -9,6 +9,7 @@ Sphinx==1.1
9 9
 
10 10
 # Testing
11 11
 nose==1.0.0
  12
+mock==0.8.0
12 13
 -e git://github.com/jbalogh/django-nose.git#egg=django_nose
13 14
 -e git://github.com/jbalogh/test-utils.git#egg=test-utils
14 15
 pyquery
17  settings/default.py
@@ -97,6 +97,7 @@
97 97
         'search': (
98 98
             'js/libs/jquery.endless-scroll.js',
99 99
             'js/infinite.js',
  100
+            'js/expand.js',
100 101
         ),
101 102
         'backbone': (
102 103
             'js/libs/underscore.js',
@@ -122,6 +123,11 @@
122 123
 # StrictTransport
123 124
 STS_SUBDOMAINS = True
124 125
 
  126
+# Not all URLs need locale.
  127
+SUPPORTED_NONLOCALES = list(base.SUPPORTED_NONLOCALES) + [
  128
+    'csp',
  129
+]
  130
+
125 131
 AUTHENTICATION_BACKENDS = ('common.backends.MozilliansBrowserID',)
126 132
 
127 133
 # BrowserID creates a user if one doesn't exist.
@@ -200,9 +206,12 @@
200 206
 
201 207
 # Django-CSP
202 208
 CSP_IMG_SRC = ("'self'", 'http://statse.webtrendslive.com',
203  
-               'https://statse.webtrendslive.com',)
  209
+               'https://statse.webtrendslive.com',
  210
+               'http://www.gravatar.com',
  211
+               'https://secure.gravatar.com',)
204 212
 CSP_SCRIPT_SRC = ("'self'", 'http://statse.webtrendslive.com',
205  
-                  'https://statse.webtrendslive.com',)
  213
+                  'https://statse.webtrendslive.com',
  214
+                  'https://browserid.org',)
206 215
 CSP_REPORT_ONLY = True
207 216
 CSP_REPORT_URI = '/csp/report'
208 217
 
@@ -222,3 +231,7 @@
222 231
 
223 232
 # This is for the commons/helper.py thumbnail.
224 233
 DEFAULT_IMAGE_SRC = path('./media/uploads/unknown.png')
  234
+
  235
+# TEMPORARY
  236
+# TODO: Remove this
  237
+KEYNOTE_FILE = None

0 notes on commit aa4a5b9

Please sign in to comment.
Something went wrong with that request. Please try again.