Skip to content
This repository was archived by the owner on Sep 19, 2018. It is now read-only.

Commit 82e8fcd

Browse files
committed
Fix merge conflict
2 parents d3d2df8 + ebf7ee8 commit 82e8fcd

File tree

12 files changed

+164
-4
lines changed

12 files changed

+164
-4
lines changed

codeweekeu/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@
209209
'social.apps.django_app.default',
210210
# django-countries country listing
211211
'django_countries',
212+
# additional info about countries
213+
'countries_plus',
212214
# avatar handling
213215
'avatar',
214216
# support for tags

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ django-appconf==0.6
1111
django-avatar==2.0
1212
django-compressor==1.4
1313
django-countries==2.0c1
14+
django-countries-plus==0.3
1415
django-debug-toolbar==1.0.1
1516
django-endless-pagination==2.0
1617
django-geoposition==0.1.5

server-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ django-appconf==0.6
1111
django-avatar==2.0
1212
django-compressor==1.4
1313
django-countries==2.0c1
14+
django-countries-plus==0.3
1415
django-debug-toolbar==1.0.1
1516
django-endless-pagination==2.0
1617
django-geoposition==0.1.5

static/scss/_768up.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@
1717
background-color: $whitesmoke;
1818
color: $black;
1919
padding-left: 25px;
20-
}
20+
}
21+

static/scss/_base.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,25 @@ LIST EVENTS STYLES
534534
}
535535
}
536536

537+
/*********************
538+
SCOREBOARD STYLES
539+
*********************/
540+
541+
.country {
542+
border-bottom:1px solid #ccc;
543+
border:1px solid #ccc;
544+
.country-name {
545+
font-weight: 800;
546+
font-size: 1.2em;
547+
}
548+
.event-number {
549+
font-weight: 800;
550+
font-size: 1.5em;
551+
}
552+
background-color: #F5F5F5;
553+
}
554+
555+
.highlighted {
556+
background-color: #F0F8FF;
557+
}
558+

web/processors/event.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.contrib.gis.geoip import GeoIP
66
from api.models import Event
77
from django_countries import countries
8+
from countries_plus.models import Country
89

910
from web.processors import media
1011
from mailer.event_report_mailer import send_email_to_country_ambassadors
@@ -120,6 +121,34 @@ def get_country(country_code, user_ip):
120121
return country
121122

122123

124+
def count_approved_events_for_country(past=True):
125+
"""
126+
Count the number of approved events and score for each country
127+
"""
128+
129+
all_events = Event.objects.filter(status='APPROVED')
130+
131+
country_count = []
132+
133+
# not including the first two fake countries in the list
134+
for country in list(countries)[2:]:
135+
country_code = country[0]
136+
country_name = country[1]
137+
number_of_events = all_events.filter(country=country_code).count()
138+
population = Country.objects.get(iso=country_code).population
139+
country_score = 0
140+
if number_of_events > 0 and population > 0 and population != "":
141+
country_score = 1. * number_of_events / population
142+
country_entry = {'country_code': country_code,
143+
'country_name': country_name,
144+
'events': number_of_events,
145+
'score': country_score}
146+
country_count.append(country_entry)
147+
148+
sorted_count = sorted(country_count, key=lambda k: k['score'], reverse=True)
149+
return sorted_count
150+
151+
123152
def change_event_status(event_id):
124153
event = Event.objects.get(pk=event_id)
125154

web/templates/pages/scoreboard.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{% extends 'base.html' %}
2+
3+
{% block title %}- Events Scoreboard{% endblock title %}
4+
5+
{% block content %}
6+
<div class="container">
7+
<h1>#codeEU Events Scoreboard</h1>
8+
<p>Which countries in Europe are buzzing with coding activity? The scoreboard is sorted by the number of listed coding events per population, so don't be surprised to see some of the smaller countries higher up on the list!</p>
9+
{% for country in counts %}
10+
<div class="col-md-6 country{% if forloop.counter < 11 %} highlighted{% endif %}">
11+
<img src="/static/flags/{{ country.country_code|lower }}.png" alt="{{ country.country_name }}" />
12+
<span class="icon-flag">
13+
<span class="country-name">{{ country.country_name }}</span> is participating with
14+
<span class="event-number"><a href="{% url 'web.search_events' %}?country_code={{ country.country_code }}&amp;past=yes">{{ country.events }}</span> event{% if country.events != 1 %}s{% endif %}</a>
15+
</span>
16+
</div>
17+
{% endfor %}
18+
</div>
19+
{% endblock content %}

web/templates/pages/view_event.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ <h1>{{ event.title }}</h1>
162162
<p>
163163
{% for tag in event.tags.all %}
164164
{% if forloop.last %}
165-
{{ tag.name }}
165+
<a href="{% url 'web.search_events' %}?q={{ tag.name|urlencode }}">{{ tag.name }}</a>
166166
{% else %}
167-
{{ tag.name }},
167+
<a href="{% url 'web.search_events' %}?q={{ tag.name|urlencode }}">{{ tag.name }}</a>,
168168
{% endif %}
169169
{% endfor %}
170170
</p>

web/tests/test_event_views.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# coding=utf-8
2+
13
import datetime
24
import pytest
35
import StringIO
@@ -60,6 +62,15 @@ def test_search_events_with_search_query(self):
6062
self.assertEquals(1,response.context['events'].count())
6163
self.assertEquals('SI', response.context['country'])
6264

65+
def test_search_events_with_unicode_tag_in_search_query(self):
66+
ApprovedEventFactory.create(tags=["jabolčna čežana","José", "Django"])
67+
response = self.client.get(reverse('web.search_events'), {'q':'čežana'}, REMOTE_ADDR='93.103.53.11')
68+
69+
self.assertEquals(1,response.context['events'].count())
70+
self.assertEquals('SI', response.context['country'])
71+
72+
73+
6374
def test_search_events_with_search_query_multiple_events(self):
6475
approved1 = ApprovedEventFactory.create(title="Event Arglebargle - Approved", country="SI")
6576
approved2 = ApprovedEventFactory.create(title="Event Arglebargle - Approved", country="AT")

web/tests/test_events_processors.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from api.processors import get_approved_events
1919
from api.processors import get_next_or_previous
2020
from api.processors import get_nearby_events
21-
21+
from web.processors.event import count_approved_events_for_country
2222

2323
class EventTestCase(TestCase):
2424
def get_user(self):
@@ -346,6 +346,7 @@ def test_create_event_in_moldova(admin_user, db):
346346
assert "MD" == test_event.country.code
347347

348348
@pytest.mark.django_db
349+
<<<<<<< HEAD
349350
def test_create_event_in_kosovo(admin_user, db):
350351
event_data = {
351352
'audience': [3],
@@ -367,3 +368,63 @@ def test_create_event_in_kosovo(admin_user, db):
367368

368369
assert "XK" == test_event.country.code
369370

371+
def test_scoreboard_counter(admin_user, db):
372+
373+
initial_counter = count_approved_events_for_country()
374+
375+
counted_events_before = 0
376+
377+
for country in initial_counter:
378+
if country['country_code'] == 'SI':
379+
counted_events_before = country['events']
380+
381+
# Adding one approved and one pending event in same country
382+
# the count for events for the country should increase by 1
383+
event_data = {
384+
'audience': [3],
385+
'theme': [1,2],
386+
'country': u'SI',
387+
'description': u'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\r\ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\r\nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\r\nconsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\r\ncillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\r\nproident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
388+
'location': u'Ljubljana, Slovenia',
389+
'organizer': u'testko',
390+
"creator": admin_user,
391+
'start_date': datetime.datetime.now(),
392+
'end_date': datetime.datetime.now() + datetime.timedelta(days=3, hours=3),
393+
'title': u'Test Approved Event',
394+
'status':"APPROVED",
395+
}
396+
397+
test_approved_event = create_or_update_event(event_id=None, **event_data)
398+
399+
event_data = {
400+
'audience': [3],
401+
'theme': [1,2],
402+
'country': u'SI',
403+
'description': u'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\r\ntempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\r\nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\r\nconsequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\r\ncillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\r\nproident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
404+
'location': u'Ljubljana, Slovenia',
405+
'organizer': u'testko',
406+
"creator": admin_user,
407+
'start_date': datetime.datetime.now(),
408+
'end_date': datetime.datetime.now() + datetime.timedelta(days=3, hours=3),
409+
'title': u'Test Pending Event',
410+
'status':"PENDING",
411+
}
412+
413+
test_pending_event = create_or_update_event(event_id=None, **event_data)
414+
415+
new_counter = count_approved_events_for_country()
416+
417+
counted_events_after = 0
418+
419+
for country in new_counter:
420+
if country['country_code'] == 'SI':
421+
counted_events_after = country['events']
422+
423+
# An extra check with a direct DB query
424+
counted_events_query = Event.objects.filter(status='APPROVED').filter(country='SI').count()
425+
426+
assert counted_events_after == counted_events_before + 1
427+
assert counted_events_after == counted_events_query
428+
429+
test_approved_event.delete()
430+
test_pending_event.delete()

web/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
url(r'^about/$', TemplateView.as_view(template_name="pages/about.html"), name='web.about'),
2121
url(r'^login/$', 'users.login', name='web.login'),
2222
url(r'^ambassadors/$', 'users.ambassadors', name='web.ambassadors'),
23+
url(r'^scoreboard/$', 'events.scoreboard', name='web.scoreboard'),
2324
url(r'^change_status/(?P<event_id>\d+)/$', 'events.change_status', name='web.change_status'),
2425
url(r'^reject_status/(?P<event_id>\d+)/$', 'events.reject_status', name='web.reject_status'),
2526
# Note: do not place any url after this one of it will not work

web/views/events.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from web.processors.event import list_countries
3131
from web.processors.event import get_country
3232
from web.processors.event import get_country_from_user_ip
33+
from web.processors.event import count_approved_events_for_country
3334
from web.processors.media import process_image
3435
from web.processors.media import ImageSizeTooLargeException
3536
from web.processors.media import UploadImageError
@@ -308,6 +309,17 @@ def search_events(request):
308309
},
309310
context_instance=RequestContext(request))
310311

312+
def scoreboard(request):
313+
template = 'pages/scoreboard.html'
314+
315+
counts = count_approved_events_for_country()
316+
317+
return render_to_response(
318+
template, {
319+
'counts': counts,
320+
},
321+
context_instance=RequestContext(request))
322+
311323

312324
@login_required
313325
@can_moderate_event

0 commit comments

Comments
 (0)