Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'develop' of github.com:mozilla/firefox-flicks into develop

  • Loading branch information...
commit e1a54cc85bc821872f3b309e7f3f1516383cad66 2 parents 39ae029 + 1acb4e6
@craigcook craigcook authored
Showing with 722 additions and 545 deletions.
  1. +2 −0  .gitignore
  2. +3 −0  .gitmodules
  3. +6 −0 flicks/base/templates/shared/header.html
  4. +57 −0 flicks/base/templates/shared/macros.html
  5. +0 −360 flicks/base/templates/winners.html
  6. +6 −6 flicks/base/urls.py
  7. +9 −1 flicks/settings/base.py
  8. +3 −2 flicks/urls.py
  9. +2 −2 flicks/users/admin.py
  10. +8 −4 flicks/videos/admin.py
  11. +91 −0 flicks/videos/migrations/0010_auto__add_award.py
  12. +103 −0 flicks/videos/migrations/0011_add_awards.py
  13. +90 −1 flicks/videos/models.py
  14. +3 −5 flicks/videos/templates/videos/details.html
  15. +1 −21 flicks/videos/templates/videos/recent.html
  16. +39 −0 flicks/videos/templates/videos/recent_contest_over.html
  17. +93 −0 flicks/videos/templates/videos/winners.html
  18. +0 −51 flicks/videos/tests/test_views.py
  19. +2 −3 flicks/videos/urls.py
  20. +41 −5 flicks/videos/views.py
  21. +108 −83 media/css/main.css
  22. +48 −0 media/js/winners.js
  23. +2 −0  requirements/compiled.txt
  24. +2 −0  requirements/prod.txt
  25. +1 −1  vendor
  26. +1 −0  vendor-local/src/django-waffle
  27. +1 −0  vendor-local/vendor.pth
View
2  .gitignore
@@ -19,3 +19,5 @@ tmp/*
*.mo
flicks/locale/templates
flicks/locale/.svn
+*.egg-info
+media/previews/*
View
3  .gitmodules
@@ -28,3 +28,6 @@
[submodule "vendor-local/src/django-statsd"]
path = vendor-local/src/django-statsd
url = git://github.com/andymckay/django-statsd.git
+[submodule "vendor-local/src/django-waffle"]
+ path = vendor-local/src/django-waffle
+ url = git://github.com/jsocol/django-waffle.git
View
6 flicks/base/templates/shared/header.html
@@ -3,6 +3,12 @@
<a href="{{ url('flicks.videos.recent') }}"
title="{{ _('Firefox Flicks') }}" class="logo">{{ _('Firefox Flicks') }}</a>
<ul>
+ {% if waffle.flag('winners_page') %}
+ <li><a href="{{ url('flicks.videos.winners')}}"
+ title="{{ _('Award') }}">
+ <img class="award" src="{{ MEDIA_URL }}img/winner-trophy-sm.png" alt="{{ _('Award') }}">
+ </a></li>
+ {% endif %}
<li><a href="{{ url('flicks.videos.recent')}}"
title="{{ _('Videos') }}">{{ _('Videos') }}</a></li>
<li><a href="{{ url('flicks.base.creative')}}"
View
57 flicks/base/templates/shared/macros.html
@@ -1,6 +1,9 @@
{% macro video_item(idx, video) -%}
<li id="slide-{{ idx }}">
<a href="{{ video.details_href }}" class="title" title="{{ video.title }}">
+ {% if video.is_winner %}
+ <img class="winner-mark" src="{{ MEDIA_URL }}img/winner-trophy-sm.png" alt="{{ _('Award') }}">
+ {% endif %}
<img src="{{ video.poster_href }}" height="141">
</a>
<div class="video-details">
@@ -14,6 +17,13 @@
{% macro video_details(video) -%}
<a href="{{ url('flicks.users.details', user_id=video.user_id) }}"
class="user">{{ video.user.userprofile.full_name }}, {{ video.user.userprofile.country }}</a>
+ {% if video.is_winner %}
+ {% for award in video.award_set.all() %}
+ <div class="winner-details">
+ {{ award.award_title }}
+ </div>
+ {% endfor %}
+ {% endif %}
<p class="region-info">
{% set category_link='<span class="category">{title}</span>'|fe(title=video.get_category_display()) %}
{% set country_link='<span class="region">{title}</span>'|fe(title=video.get_region_display()) %}
@@ -121,3 +131,50 @@
</p>
{% endif %}
{%- endmacro %}
+
+{% macro award_region(region_name, region_key) -%}
+ <h1>{{ region_name }}</h1>
+
+ <section class="grandprize">
+ {% set key = 'grand_winner__%s'|format(region_key) %}
+ {{ large_award(awards[key]) }}
+ </section>
+
+ <section class="category">
+ <h2>{{ _('Category Winners') }}</h2>
+ <ul>
+ {% for category_key, category_name in category_choices %}
+ {% set key = 'category_winner__%s__%s'|format(region_key, category_key) %}
+ {{ small_award(category_name, awards[key]) }}
+ {% endfor %}
+ </ul>
+ </section>
+
+ <section class="runnerups">
+ <h2>{{ _('Runner Ups') }}</h2>
+ <ul>
+ {% for category_key, category_name in category_choices %}
+ {% set key = 'runner_up__%s__%s'|format(region_key, category_key) %}
+ {{ small_award(category_name, awards[key]) }}
+ {% endfor %}
+ </ul>
+ </section>
+{%- endmacro %}
+
+{% macro large_award(award) -%}
+ <h2 class="title">
+ <a href="{{ award.video_href }}">
+ <img src="{{ award.video_preview }}" alt="{{ award.video_title }}" width="600" height="342">
+ {{ award.video_title }}
+ </a>
+ </h2>
+ <p class="credit">{{ award.submitter_name }}, {{ award.submitter_country }}</p>
+{%- endmacro %}
+
+{% macro small_award(category_name, award) -%}
+ <li>
+ <h3>{{ category_name }}</h3>
+ <h4 class="title"><a href="{{ award.video_href }}">{{ award.video_title }}</a></h4>
+ <p class="credit">{{ award.submitter_name }}, {{ award.submitter_country }}</p>
+ </li>
+{%- endmacro %}
View
360 flicks/base/templates/winners.html
@@ -1,360 +0,0 @@
-<!-- Standard doc header goes here -->
-
-<!-- note the 'winners' body class. We need this as a style hook. -->
-<body class="winners">
-
-<div class="wrapper">
-
-<!-- Standard site header, but we're updating the navigation. -->
- <div id="header">
- <div class="header-wrapper">
- <a href="https://firefoxflicks.mozilla.org/" title="Firefox Flicks" class="logo">Firefox Flicks</a>
- <ul>
- <li><a href="https://firefoxflicks.mozilla.org/en-US/winners" title="Winners">Winners</a></li>
- <li><a href="https://firefoxflicks.mozilla.org/en-US/recent" title="Videos">Videos</a></li>
- <li><a href="https://firefoxflicks.mozilla.org/en-US/judges" title="Judges">Judges</a></li>
- <li><a href="https://firefoxflicks.mozilla.org/en-US/prizes" title="Prizes">Prizes</a></li>
- <li><a href="https://firefoxflicks.mozilla.org/en-US/faq" title="FAQ">FAQ</a></li>
- <li><a href="https://firefoxflicks.mozilla.org/en-US/rules" title="Rules">Rules</a></li>
- </ul>
- <a href="http://mozilla.org/" id="mozilla-tag">Mozilla</a>
- </div>
- </div>
-
- <div class="content-wrapper">
- <!-- new stuff starts here -->
- <header class="winners-head">
- <h1>And the <span>Awards Go To&hellip;</span></h1>
-
- <div class="headline">
- <p class="intro-description">Our illustrious judges have watched the flicks, laughed their laughs, shed
- their tears and they’ve made their decisions. It wasn’t easy thanks to all the
- amazing entries, but here they are, ladies and gentlemen, the winners of Firefox
- Flicks 2012.</p>
- <p class="intro-description">Thanks to everyone who took the time to make and submit a video to help us
- share the story of Firefox with the world.</p>
- </div>
- </header>
-
- <nav id="nav-sections">
- <ul>
- <li><a href="#section-asia">Asia, Africa, Australia</a></li>
- <li><a href="#section-europe">Europe</a></li>
- <li><a href="#section-latam">Latin America</a></li>
- <li><a href="#section-northam">North America</a></li>
- <li><a href="#section-panavision">Panavision</a></li>
- <li><a href="#section-bayarea">Bay Area Video Coalition</a></li>
- </ul>
- </nav>
-
- <article id="section-asia" class="section">
- <h1>Asia, Africa, &amp; Australia</h1>
-
- <section class="grandprize">
- <h2 class="title"><a href="#"><img src="/media/img/promo-twilight.jpg" alt="" width="600" height="342"> Video Title</a></h2>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </section>
-
- <section class="category">
- <h2>Category Winners</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
-
- <section class="runnerups">
- <h2>Runner Ups</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
- </article>
-
- <article id="section-europe" class="section">
- <h1>Europe</h1>
-
- <section class="grandprize">
- <h2 class="title"><a href="#"><img src="/media/img/promo-twilight.jpg" alt="" width="600" height="342"> Video Title</a></h2>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </section>
-
- <section class="category">
- <h2>Category Winners</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
-
- <section class="runnerups">
- <h2>Runner Ups</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
- </article>
-
- <article id="section-latam" class="section">
- <h1>Latin America</h1>
-
- <section class="grandprize">
- <h2 class="title"><a href="#"><img src="/media/img/promo-twilight.jpg" alt="" width="600" height="342"> Video Title</a></h2>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </section>
-
- <section class="category">
- <h2>Category Winners</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
-
- <section class="runnerups">
- <h2>Runner Ups</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
- </article>
-
- <article id="section-northam" class="section">
- <h1>North America</h1>
-
- <section class="grandprize">
- <h2 class="title"><a href="#"><img src="/media/img/promo-twilight.jpg" alt="" width="600" height="342"> Video Title</a></h2>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </section>
-
- <section class="category">
- <h2>Category Winners</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
-
- <section class="runnerups">
- <h2>Runner Ups</h2>
- <ul>
- <li>
- <h3>30 Second Spot</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>Animation</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>New Technology</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- <li>
- <h3>PSA</h3>
- <h4 class="title"><a href="#">Video Title</a></h4>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </li>
- </ul>
- </section>
- </article>
-
- <article id="section-panavision" class="section">
- <h1>Winner: Panavision Prize</h1>
-
- <section class="grandprize">
- <h2 class="title"><a href="#"><img src="/media/img/promo-twilight.jpg" alt="" width="600" height="342"> Video Title</a></h2>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </section>
-
- </article>
-
- <article id="section-bayarea" class="section">
- <h1>Winner: Bay Area Video Coalition</h1>
-
- <section class="grandprize">
- <h2 class="title"><a href="#"><img src="/media/img/promo-twilight.jpg" alt="" width="600" height="342"> Video Title</a></h2>
- <p class="credit">Submitter Name, Submitter Locale</p>
- </section>
- </article>
-
-
- </div><!-- /.content-wrapper -->
-
-<!-- Standard footer goes here -->
-
-<!-- This script should be moved to an external file, either on its own or conglomerated -->
-<script>
-(function ($) {
-
- var $window = $(window),
- $content = $(".content-wrapper"),
- $nav = $("#nav-sections"),
- navTop = $nav.offset(),
- navHeight = $nav.height()+24,
- fixed = false;
-
- $window.scroll(function() {
-
- var scrollTop = $window.scrollTop();
-
- if( scrollTop >= navTop.top ) {
- if( !fixed ) {
- fixed = true;
- $nav.addClass("fixed");
- $content.css({ paddingTop: navHeight+24 });
- }
- }
- else {
- if( fixed ) {
- fixed = false;
- $nav.removeClass("fixed");
- $content.css({ paddingTop: "0" });
- }
- }
-
- });
-
- $("#nav-sections a").click(function(){
- /* extract the target element's ID from the link's href */
- var target = $(this).attr("href").replace( /.*?#(.*)/g, "$1" );
- $('html, body').animate({
- scrollTop: $("#"+target).offset().top-navHeight
- }, 1000);
- return false;
- });
-
-})(jQuery);
-</script>
View
12 flicks/base/urls.py
@@ -3,10 +3,10 @@
from flicks.base import views
urlpatterns = patterns('',
- url(r'^creative$', views.creative, name='flicks.base.creative'),
- url(r'^faq$', views.faq, name='flicks.base.faq'),
- url(r'^judges$', views.judges, name='flicks.base.judges'),
- url(r'^partners$', views.partners, name='flicks.base.partners'),
- url(r'^prizes$', views.prizes, name='flicks.base.prizes'),
- url(r'^rules$', views.rules, name='flicks.base.rules'),
+ url(r'^creative/?$', views.creative, name='flicks.base.creative'),
+ url(r'^faq/?$', views.faq, name='flicks.base.faq'),
+ url(r'^judges/?$', views.judges, name='flicks.base.judges'),
+ url(r'^partners/?$', views.partners, name='flicks.base.partners'),
+ url(r'^prizes/?$', views.prizes, name='flicks.base.prizes'),
+ url(r'^rules/?$', views.rules, name='flicks.base.rules'),
)
View
10 flicks/settings/base.py
@@ -21,7 +21,6 @@
),
'video_details': (
'js/libs/script.js',
- 'js/vote.js',
'js/views.js',
'js/share.js',
),
@@ -29,6 +28,9 @@
'js/libs/script.js',
'js/share.js',
),
+ 'winners': (
+ 'js/winners.js',
+ )
}
}
@@ -77,6 +79,7 @@
'django_browserid',
'django_statsd',
'south',
+ 'waffle',
]
MIDDLEWARE_CLASSES = list(MIDDLEWARE_CLASSES) + [
@@ -84,6 +87,7 @@
'csp.middleware.CSPMiddleware',
'django_statsd.middleware.GraphiteRequestTimingMiddleware',
'django_statsd.middleware.GraphiteMiddleware',
+ 'waffle.middleware.WaffleMiddleware',
]
AUTH_PROFILE_MODULE = 'flicks.UserProfile'
@@ -213,3 +217,7 @@
'django_statsd.patches.db',
'django_statsd.patches.cache',
]
+
+# Video preview settings
+PREVIEW_PATH = lambda inst, filename: 'previews/%s_%s' % (inst.id, filename)
+MAX_FILEPATH_LENGTH = 100
View
5 flicks/urls.py
@@ -1,10 +1,11 @@
from django.conf import settings
from django.conf.urls.defaults import include, patterns, url
+from django.contrib import admin
from django.contrib.admin import autodiscover
from django.shortcuts import render
-from funfactory import admin
-
+from funfactory.monkeypatches import patch
+patch()
# Autodiscover admin.py files in each app
autodiscover()
View
4 flicks/users/admin.py
@@ -1,8 +1,7 @@
+from django.contrib.admin import site
from django.contrib.auth import admin
from django.contrib.auth.models import User
-from funfactory.admin import site
-
class UserAdmin(admin.UserAdmin):
"""Configuration for the user admin pages."""
@@ -19,4 +18,5 @@ def country(self, user):
def youth_contest(self, user):
return user.userprofile.youth_contest
youth_contest.boolean = True
+site.unregister(User)
site.register(User, UserAdmin)
View
12 flicks/videos/admin.py
@@ -1,8 +1,6 @@
from django.contrib import admin
-from funfactory.admin import site
-
-from flicks.videos.models import Video
+from flicks.videos.models import Award, Video
class VideoAdmin(admin.ModelAdmin):
@@ -11,4 +9,10 @@ class VideoAdmin(admin.ModelAdmin):
'region', 'shortlink', 'created']
list_filter = ['state', 'judge_mark', 'category', 'region']
search_fields = ['title', 'description', 'user__email']
-site.register(Video, VideoAdmin)
+admin.site.register(Video, VideoAdmin)
+
+
+class AwardAdmin(admin.ModelAdmin):
+ """Configuration for the award admin pages."""
+ list_display = ['region', 'award_type', 'category', 'video', 'preview']
+admin.site.register(Award, AwardAdmin)
View
91 flicks/videos/migrations/0010_auto__add_award.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'Award'
+ db.create_table('videos_award', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('video', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['videos.Video'], null=True, blank=True)),
+ ('preview', self.gf('django.db.models.fields.files.ImageField')(max_length=100)),
+ ('category', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ('region', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ('award_type', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ))
+ db.send_create_signal('videos', ['Award'])
+
+ def backwards(self, orm):
+ # Deleting model 'Award'
+ db.delete_table('videos_award')
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'videos.award': {
+ 'Meta': {'object_name': 'Award'},
+ 'award_type': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'category': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'preview': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+ 'region': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'video': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['videos.Video']", 'null': 'True', 'blank': 'True'})
+ },
+ 'videos.video': {
+ 'Meta': {'object_name': 'Video'},
+ 'bitly_link_db': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200', 'blank': 'True'}),
+ 'category': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 2, 28, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'judge_mark': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'region': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'shortlink': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.CharField', [], {'default': "'unsent'", 'max_length': '10'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'upload_url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'views': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
+ 'votes': ('django.db.models.fields.BigIntegerField', [], {'default': '0'})
+ }
+ }
+
+ complete_apps = ['videos']
View
103 flicks/videos/migrations/0011_add_awards.py
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+from itertools import product
+
+from south.v2 import DataMigration
+
+from flicks.videos.models import Award
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ """Create awards."""
+ regions = ['america', 'latin_america', 'europe',
+ 'asia_africa_australia']
+ categories = ['thirty_spot', 'animation', 'new_technology', 'psa']
+
+ # Grand prize winners
+ for region in regions:
+ Award.objects.create(award_type='grand_winner', region=region)
+
+ # Category winners and runner ups.
+ for award_type, region, category in product(
+ ['category_winner', 'runner_up'], regions, categories):
+ Award.objects.create(award_type=award_type, region=region,
+ category=category)
+
+ # Special awards
+ Award.objects.create(award_type='panavision')
+ Award.objects.create(award_type='panavision')
+ Award.objects.create(award_type='bavc')
+
+
+ def backwards(self, orm):
+ """Remove all awards from the DB."""
+ Award.objects.all().delete()
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'videos.award': {
+ 'Meta': {'object_name': 'Award'},
+ 'award_type': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'category': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'preview': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}),
+ 'region': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'video': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['videos.Video']", 'null': 'True', 'blank': 'True'})
+ },
+ 'videos.video': {
+ 'Meta': {'object_name': 'Video'},
+ 'bitly_link_db': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200', 'blank': 'True'}),
+ 'category': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 2, 28, 0, 0)', 'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'judge_mark': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'region': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'shortlink': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
+ 'state': ('django.db.models.fields.CharField', [], {'default': "'unsent'", 'max_length': '10'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'upload_url': ('django.db.models.fields.URLField', [], {'default': "''", 'max_length': '200'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'views': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
+ 'votes': ('django.db.models.fields.BigIntegerField', [], {'default': '0'})
+ }
+ }
+
+ complete_apps = ['videos']
+ symmetrical = True
View
91 flicks/videos/models.py
@@ -12,7 +12,7 @@
from elasticutils.tasks import index_objects, unindex_objects
from funfactory.urlresolvers import reverse, split_path
from jinja2 import Markup
-from tower import ugettext_lazy as _lazy
+from tower import ugettext as _, ugettext_lazy as _lazy
from flicks.base.util import absolutify, generate_bitly_link
from flicks.videos.tasks import add_vote
@@ -41,6 +41,21 @@
('asia_africa_australia', _lazy('Asia, Africa & Australia'))
)
+# Untranslated as they're only seen in the admin interface.
+AWARD_TYPE_CHOICES = (
+ ('grand_winner', 'Grand Prize Winner'),
+ ('category_winner', 'Category Winner'),
+ ('runner_up', 'Runner Up'),
+ ('panavision', 'Panavision Prize'),
+ ('bavc', 'Bay Area Video Coalition')
+)
+
+WINNER_CATEGORY_TEXT = {
+ 'thirty_spot': _lazy('30 Second Spot Winner'),
+ 'animation': _lazy('Animation Winner'),
+ 'new_technology': _lazy('New Technology Winner'),
+ 'psa': _lazy('PSA Winner')
+}
class Video(models.Model, SearchMixin, CachingMixin):
"""Users can only have one video associated with
@@ -119,6 +134,11 @@ def bitly_link(self):
Video.objects.filter(pk=self.pk).update(bitly_link_db=bitly_link)
return bitly_link
+ @property
+ def is_winner(self):
+ """Return true if this video won an award."""
+ return Award.objects.filter(video=self).exists()
+
def upvote(self):
"""Add an upvote to this video."""
add_vote.delay(self)
@@ -164,3 +184,72 @@ def post_save(sender, instance, **kwargs):
"""Invalidate VIEWS_KEY when video is saved."""
from flicks.videos.util import VIEWS_KEY
cache.delete(VIEWS_KEY % instance.id)
+
+
+class Award(models.Model, CachingMixin):
+ """Model for contest winners."""
+ video = models.ForeignKey(Video, blank=True, null=True)
+ preview = models.ImageField(blank=True, upload_to=settings.PREVIEW_PATH,
+ max_length=settings.MAX_FILEPATH_LENGTH)
+ category = models.CharField(max_length=50, blank=True,
+ choices=CATEGORY_CHOICES,
+ verbose_name=_lazy(u'Category'))
+ region = models.CharField(max_length=50, blank=True,
+ choices=REGION_CHOICES,
+ verbose_name=_lazy(u'Region'))
+ award_type = models.CharField(max_length=50, blank=False,
+ choices = AWARD_TYPE_CHOICES)
+
+ objects = CachingManager()
+
+ @property
+ def award_title(self):
+ if self.award_type == 'grand_winner':
+ return _('%(winner)s for %(region)s') % {
+ 'winner': _('Grand Prize Winner'),
+ 'region': self.get_region_display()
+ }
+ elif self.award_type == 'bavc':
+ return _('Bay Area Video Coalition Prize Winner')
+ elif self.award_type == 'panavision':
+ return _('Panavision Prize Winner')
+ else:
+ return _('%(winner)s for %(region)s') % {
+ 'winner': unicode(WINNER_CATEGORY_TEXT[self.category]),
+ 'region': self.get_region_display()
+ }
+
+ @property
+ def video_title(self):
+ if self.video is None:
+ return 'Video Title'
+ else:
+ return self.video.title
+
+ @property
+ def video_href(self):
+ if self.video is None:
+ return '#'
+ else:
+ return self.video.details_href
+
+ @property
+ def video_preview(self):
+ if not self.preview:
+ return '{0}img/promo-twilight.jpg'.format(settings.MEDIA_URL)
+ else:
+ return self.preview.url
+
+ @property
+ def submitter_name(self):
+ if self.video is None:
+ return 'Submitter Name'
+ else:
+ return self.video.user.userprofile.full_name
+
+ @property
+ def submitter_country(self):
+ if self.video is None:
+ return 'Submitter Country'
+ else:
+ return self.video.user.userprofile.country
View
8 flicks/videos/templates/videos/details.html
@@ -28,11 +28,9 @@
<div class="video-content">
<div class="video-wrapper">
{{ video.embed_html }}
- {# L10n: Refers to a user voting up a video. #}
- <a id="upvote" class="vote" data-shortlink="{{ video.shortlink }}"
- data-upvote-url="{{ url('flicks.videos.upvote', video.shortlink) }}"
- data-token="{{ csrf_token }}" data-votes="{{ video.votes }}"
- title="{{ _('Upvote') }}">{{ video.votes }}</a>
+ {% if video.is_winner %}
+ <img class="winner-mark" src="{{ MEDIA_URL }}img/winner-trophy-sm.png" alt="{{ _('Award') }}">
+ {% endif %}
</div>
<div id="judge_mark">
{# Do not mark for l10n: Strings are for admins only! #}
View
22 flicks/videos/templates/videos/recent.html
@@ -10,30 +10,10 @@
{% block page_title %}{{ title }}{% endblock %}
{% block content %}
- <h1>{{ _("That's a wrap!") }}</h1>
- <div class="headline">
- <p class="intro-description">
- {% trans %}
- Thanks to everyone for the awesome flicks. Our judges are now sequestered (with
- plenty of popcorn) to choose the winners, but you can still watch the entries and
- share your favorites while you wait for the big announcement on May 17.
- {% endtrans %}
- </p>
- </div>
+ <h1>{{ title }}</h1>
<form>
{{ display_search_form(search_form) }}
</form>
{{ search_results(videos, show_pagination, video_pages) }}
{% endblock %}
-
-{% block homefooter %}
- <section id="social">
- <h3>{{ _('Flicks News') }}</h3>
- {# Social media text stays as is and is not to be translated. #}
- <a href="https://twitter.com/#!/FirefoxFlicks" class="social-share share-twitter">Twitter</a>
- <a href="https://www.facebook.com/FirefoxFlicks" class="social-share share-facebook">Facebook</a>
- <a href="http://firefoxflicks.tumblr.com" class="social-share share-tumblr">Tumblr</a>
- <a href="http://www.flickr.com/photos/firefoxflicks" class="social-share share-flickr">Flickr</a>
- </section>
-{% endblock %}
View
39 flicks/videos/templates/videos/recent_contest_over.html
@@ -0,0 +1,39 @@
+{% extends 'base.html' %}
+{% from 'shared/macros.html' import paginate, display_search_form, search_results, video_item %}
+
+{% if search %}
+ {% set title=_('Video Search Results') %}
+{% else %}
+ {% set title=_('Videos') %}
+{% endif %}
+
+{% block page_title %}{{ title }}{% endblock %}
+
+{% block content %}
+ <h1>{{ _("That's a wrap!") }}</h1>
+ <div class="headline">
+ <p class="intro-description">
+ {% trans %}
+ Thanks to everyone for the awesome flicks. Our judges are now sequestered (with
+ plenty of popcorn) to choose the winners, but you can still watch the entries and
+ share your favorites while you wait for the big announcement on May 17.
+ {% endtrans %}
+ </p>
+ </div>
+ <form action="{{ url('flicks.videos.recent') }}" method="GET">
+ {{ display_search_form(search_form) }}
+ </form>
+
+ {{ search_results(videos, show_pagination, video_pages) }}
+{% endblock %}
+
+{% block homefooter %}
+ <section id="social">
+ <h3>{{ _('Flicks News') }}</h3>
+ {# Social media text stays as is and is not to be translated. #}
+ <a href="https://twitter.com/#!/FirefoxFlicks" class="social-share share-twitter">Twitter</a>
+ <a href="https://www.facebook.com/FirefoxFlicks" class="social-share share-facebook">Facebook</a>
+ <a href="http://firefoxflicks.tumblr.com" class="social-share share-tumblr">Tumblr</a>
+ <a href="http://www.flickr.com/photos/firefoxflicks" class="social-share share-flickr">Flickr</a>
+ </section>
+{% endblock %}
View
93 flicks/videos/templates/videos/winners.html
@@ -0,0 +1,93 @@
+{% extends 'base.html' %}
+{% from 'shared/macros.html' import award_region, large_award with context %}
+
+{% block page_title %}{{ _('Winners') }}{% endblock %}
+
+{% block site_js %}
+ {{ super() }}
+ {{ js('winners') }}
+{% endblock %}
+
+{% block userbar %}{% endblock %}
+
+{% block content %}
+ <header class="winners-head">
+ <h1>{{ _('And the awards go to...') }}</h1>
+
+ <div class="headline">
+ <p class="intro-description">
+ {% trans %}
+ Our illustrious judges have watched the flicks, laughed
+ their laughs, shed their tears and they've made their
+ decisions. It wasn't easy thanks to all the amazing entries,
+ but here they are, ladies and gentlemen, the winners of
+ Firefox Flicks 2012.
+ {% endtrans %}
+ </p>
+ <p class="intro-description">
+ {% trans %}
+ Thanks to everyone who took the time to make and submit a
+ video to help us share the story of Firefox with the world.
+ {% endtrans %}
+ </p>
+ </div>
+ </header>
+
+ <nav id="nav-sections">
+ <ul>
+ <li><a href="#section-asia">{{ _('Asia, Africa & Australia') }}</a></li>
+ <li><a href="#section-europe">{{ _('Europe') }}</a></li>
+ <li><a href="#section-latam">{{ _('Latin America') }}</a></li>
+ <li><a href="#section-northam">{{ _('North America') }}</a></li>
+ <li><a href="#section-panavision">Panavision</a></li>
+ <li><a href="#section-bayarea">Bay Area Video Coalition</a></li>
+ </ul>
+ </nav>
+
+ <article id="section-asia" class="section">
+ {{ award_region(_('Asia, Africa & Australia'), 'asia_africa_australia') }}
+ </article>
+
+ <article id="section-europe" class="section">
+ {{ award_region(_('Europe'), 'europe') }}
+ </article>
+
+ <article id="section-latam" class="section">
+ {{ award_region(_('Latin America'), 'latin_america') }}
+ </article>
+
+ <article id="section-northam" class="section">
+ {{ award_region(_('North America'), 'america') }}
+ </article>
+
+ <article id="section-panavision" class="section">
+ <h1>{{ _('Panavision Prize Winner') }}</h1>
+
+ {% for award in awards['panavision'] %}
+ <section class="grandprize">
+ {{ large_award(award) }}
+ </section>
+ {% endfor %}
+
+ </article>
+
+ <article id="section-bayarea" class="section">
+ <h1>{{ _('Bay Area Video Coalition Prize Winner') }}</h1>
+
+ <section class="grandprize">
+ {{ large_award(awards['bavc']) }}
+ </section>
+ </article>
+
+{% endblock %}
+
+{% block homefooter %}
+ <section id="social">
+ <h3>{{ _('Flicks News') }}</h3>
+ {# Social media text stays as is and is not to be translated. #}
+ <a href="https://twitter.com/#!/FirefoxFlicks" class="social-share share-twitter">Twitter</a>
+ <a href="https://www.facebook.com/FirefoxFlicks" class="social-share share-facebook">Facebook</a>
+ <a href="http://firefoxflicks.tumblr.com" class="social-share share-tumblr">Tumblr</a>
+ <a href="http://www.flickr.com/photos/firefoxflicks" class="social-share share-flickr">Flickr</a>
+ </section>
+{% endblock %}
View
51 flicks/videos/tests/test_views.py
@@ -144,57 +144,6 @@ def test_error_notification(self):
eq_(mail.outbox[0].to, [self.user.email])
-class UpvoteTests(TestCase):
- def setUp(self):
- self._build_video = build_video(self.build_user())
- self.video = self._build_video.__enter__()
-
- def tearDown(self):
- self._build_video.__exit__(None, None, None)
-
- def _post(self, shortlink):
- with self.activate('en-US'):
- kwargs = {'video_shortlink': shortlink}
- response = self.client.post(reverse('flicks.videos.upvote',
- kwargs=kwargs))
- return response
-
- def test_already_voted(self):
- """If the user already voted, return a 403 Forbidden."""
- self.client.cookies[self.video.shortlink] = '1'
- response = self._post(self.video.shortlink)
- eq_(response.status_code, 403)
- del self.client.cookies[self.video.shortlink]
-
- def test_video_doesnt_exist(self):
- """If a video with the given shortlink doesn't exist, return a
- 404 Not Found.
- """
- response = self._post('nonexistant_shortlink')
- eq_(response.status_code, 404)
-
- @patch.object(Video, 'upvote')
- def test_socket_timeout(self, video_upvote):
- """If there is an issue connecting to celery, return a
- 500 Internal Server Error.
- """
- video_upvote.side_effect = socket.timeout
- response = self._post(self.video.shortlink)
- eq_(response.status_code, 500)
-
- def test_successful_upvote(self):
- """If no error occurs, the video vote count should increase, a cookie
- should be set, and the server should return a 200 Ok.
- """
- votes = self.video.votes
- response = self._post(self.video.shortlink)
- eq_(response.status_code, 200)
- ok_(self.video.shortlink in self.client.cookies)
-
- self.video = Video.objects.get(pk=self.video.pk)
- eq_(self.video.votes, votes + 1)
-
-
class AjaxAddViewTests(TestCase):
def _post(self, video_id=None):
params = {'video_id': video_id} if video_id is not None else {}
View
5 flicks/videos/urls.py
@@ -3,14 +3,13 @@
from flicks.videos import views
urlpatterns = patterns('',
- url(r'^/?$', views.recent, name='flicks.videos.recent'),
+ url(r'^/?$', views.winners, name='flicks.videos.winners'),
+ url(r'^winners/?$', views.winners, name='flicks.base.winners'),
url(r'^recent/?$', views.recent, name='flicks.videos.recent'),
url(r'^video/(?P<video_id>\d+)$', views.details,
name='flicks.videos.details'),
url(r'^add_view/?$', views.ajax_add_view,
name='flicks.videos.add_view'),
- url(r'^upvote/(?P<video_shortlink>[\w]+)$', views.upvote,
- name='flicks.videos.upvote'),
url(r'^video/noir/$', views.promo_video_noir,
name='flicks.videos.promo_video_noir'),
url(r'^video/dance/$', views.promo_video_dance,
View
46 flicks/videos/views.py
@@ -9,12 +9,13 @@
from jinja2 import Markup
import commonware.log
+import waffle
from django_statsd.clients import statsd
from tower import ugettext_lazy as _lazy
-from flicks.base.util import get_object_or_none, promo_video_shortlink
+from flicks.base.util import get_object_or_none, promo_video_shortlink, redirect
from flicks.videos.forms import SearchForm
-from flicks.videos.models import Video
+from flicks.videos.models import CATEGORY_CHOICES, Award, Video
from flicks.videos.util import add_view, cached_viewcount
from flicks.videos.vidly import embedCode
@@ -23,6 +24,35 @@
log = commonware.log.getLogger('f.videos')
+def winners(request):
+ """Winners page."""
+ if not waffle.flag_is_active(request, 'winners_page'):
+ return redirect('flicks.videos.recent')
+
+ d = dict(
+ awards={},
+ category_choices=CATEGORY_CHOICES,
+ page_type='winners'
+ )
+
+ # Add awards to template context
+ grand_prize_awards = Award.objects.filter(award_type='grand_winner')
+ for a in grand_prize_awards:
+ key = '{0}__{1}'.format(a.award_type, a.region)
+ d['awards'][key] = a
+
+ awards = Award.objects.filter(award_type__in=['category_winner',
+ 'runner_up'])
+ for a in awards:
+ key = '{0}__{1}__{2}'.format(a.award_type, a.region, a.category)
+ d['awards'][key] = a
+
+ d['awards']['panavision'] = Award.objects.filter(award_type='panavision')
+ d['awards']['bavc'] = Award.objects.get(award_type='bavc')
+
+ return render(request, 'videos/winners.html', d)
+
+
def recent(request):
"""List all videos, by recency."""
show_pagination = False
@@ -53,10 +83,16 @@ def recent(request):
search=False,
videos=videos.object_list,
video_pages=videos,
- show_pagination=show_pagination,
- page_type='secondary recent')
+ show_pagination=show_pagination)
+
+ if waffle.flag_is_active(request, 'winners_page'):
+ template = 'videos/recent.html'
+ d['page_type'] = 'secondary recent'
+ else:
+ template = 'videos/recent_contest_over.html'
+ d['page_type'] = 'secondary recent closed'
- return render(request, 'videos/recent.html', d)
+ return render(request, template, d)
def details(request, video_id=None):
View
191 media/css/main.css
@@ -99,11 +99,13 @@ div.field.agreement label a {
font-family: 'Open Sans Condensed', sans-serif;
font-size: 18px;
font-weight: 300;
+ height: 24px;
+ line-height: 24px;
margin: 0px 10px;
padding: 4px 20px 6px 60px;
text-decoration: none;
text-transform: uppercase;
- vertical-align: text-bottom;
+ vertical-align: middle;
-moz-transition: border 0.3s ease-out 0s;
width: 50px;
}
@@ -175,7 +177,6 @@ body.form .profile-header {
ol.videos li {
float: left;
- height: 345px;
list-style-type: none;
margin: 0px 15px 35px 15px;
overflow: hidden;
@@ -183,6 +184,10 @@ ol.videos li {
width: 252px;
}
+.videos li:nth-child(3n+1) {
+ clear: left;
+}
+
.user-details .left-col {
float: left;
margin-top: 3px;
@@ -353,20 +358,24 @@ html[lang="tr"] #header {
height: 268px;
}
-.recent section {
+#social {
clear: both;
display: block;
- margin: 10px 0px 25px;
- padding: 30px 0px 40px;
+ height: 110px;
+ line-height: 110px;
+ margin-bottom: 30px;
text-align: center;
+ white-space: nowrap;
}
-.recent section h3 {
- display: inline;
+#social h3 {
+ display: inline-block;
font-size: 44px;
padding: 0px 20px 0px 0px;
text-transform: uppercase;
- width: auto;
+ vertical-align: middle;
+ width: 200px;
+ white-space: normal;
}
/* @Winners ***/
@@ -403,12 +412,13 @@ body.winners #header {
}
.winners .winners-head h1 {
- text-align: left;
+ text-align: center;
float: none;
- color: #e25b31;
+ color: #fbae53;
font-size: 72px;
+ height: 130px;
line-height: 1;
- padding: 30px 0 0 360px;
+ padding: 30px 120px 0 360px;
}
.winners .winners-head h1 span {
@@ -416,7 +426,19 @@ body.winners #header {
color: #fbae53;
}
-#nav-sections.fixed {
+.winner-mark {
+ position: absolute;
+ right: 10px;
+ top: 10px;
+}
+
+.winner-details {
+ color: #fbae53;
+ clear: both;
+ font-size: 14px;
+}
+
+#nav-sections.fixed {
position: fixed;
top: 0;
width: 896px;
@@ -432,10 +454,10 @@ body.winners #header {
}
#nav-sections ul {
- background-color: #fff;
+ background-color: #fff;
text-align: center;
- margin: 0 -48px;
- padding: 0 20px;
+ margin: 0 -48px;
+ padding: 0 20px;
font: 16px/1.2 'Open Sans Light', sans-serif;
-ms-box-shadow: 0 1px 1px rgba(0,0,0,0.1);
-o-box-shadow: 0 1px 1px rgba(0,0,0,0.1);
@@ -444,19 +466,19 @@ body.winners #header {
list-style: none;
}
-#nav-sections li {
- display: inline-block;
- padding: 12px 0;
+#nav-sections li {
+ display: inline-block;
+ padding: 12px 0;
}
-#nav-sections a:link {
- display: inline-block;
- padding: 6px 15px;
- border-left: 1px dotted #ccc;
+#nav-sections a:link {
+ display: inline-block;
+ padding: 6px 15px;
+ border-left: 1px dotted #ccc;
}
-#nav-sections li:first-child a {
- border-left: 0;
+#nav-sections li:first-child a {
+ border-left: 0;
}
#nav-sections a:link,
@@ -506,7 +528,7 @@ body.winners #header {
}
.section h1,
-.section h2,
+.section h2,
.section h3 {
float: none;
line-height: 1.2;
@@ -530,7 +552,7 @@ body.winners #header {
}
.section .category {
- width: 28%;
+ width: 28%;
float: right;
margin: 0 0 24px;
}
@@ -647,23 +669,21 @@ body.winners #header {
width: 230px;
}
- .recent section .social-share {
+ .social-share {
background-position: -10px 50%;
- display: block;
- float: right;
margin-right: 0px;
padding: 6px 12px 6px 45px;
}
- .recent section .social-share.share-facebook {
+ .social-share.share-facebook {
background-position: -279px 50%;
}
- .recent section .social-share.share-tumblr {
+ .social-share.share-tumblr {
background-position: -140px 50%;
}
- .recent section .social-share.share-flickr {
+ .social-share.share-flickr {
background-position: -435px 50%;
}
@@ -671,27 +691,27 @@ body.winners #header {
.video-view p.video-info {
width: 400px;
}
-
+
body.winners #header {
background-image: none;
}
-
+
.winners .winners-head h1 {
padding: 30px 0 0 270px;
}
-
- #nav-sections.fixed {
+
+ #nav-sections.fixed {
width: 712px;
}
-
+
#nav-sections ul {
font-size: 14px;
}
-
+
#nav-sections li {
padding: 6px 0;
}
-
+
#nav-sections a:link {
padding: 6px 12px;
}
@@ -712,7 +732,7 @@ body.winners #header {
.content-wrapper, .header-wrapper, .info, .footer-wrapper {
width: 252px;
}
-
+
#header ul {
margin: 0;
clear: both;
@@ -731,16 +751,20 @@ body.winners #header {
height: 225px;
width: 400px;
}
-
+
.winners .winners-head {
background: url('../img/winner-trophy-lg.png') left top no-repeat;
}
-
+
.winners .winners-head h1 {
font-size: 48px;
padding: 30px 0 0 180px;
}
-
+
+ .winners .winners-head .headline {
+ padding-top: 20px;
+ }
+
#nav-sections,
#nav-sections.fixed {
width: 348px;
@@ -749,38 +773,38 @@ body.winners #header {
#nav-sections ul {
float: none;
- list-style: none;
- margin: 0;
+ list-style: none;
+ margin: 0;
}
-
- #nav-sections li {
- display: block;
+
+ #nav-sections li {
+ display: block;
padding: 8px 0;
border-left: 0;
- border-top: 1px dotted #ccc;
+ border-top: 1px dotted #ccc;
}
-
+
#nav-sections li:first-child {
border-top: 0;
}
-
+
#nav-sections a:link,
#nav-sections a:visited {
border: 0;
padding: 0;
}
-
+
.grandprize {
float: none;
width: 100%;
}
-
+
.section .category {
float: none;
clear: both;
width: 100%;
}
-
+
.category ul {
list-style: none;
width: 100%;
@@ -791,12 +815,11 @@ body.winners #header {
float: none;
width: auto;
}
-
+
.category h3,
.runnerups h3 {
font-size: 20px;
}
-
}
/* @Wide @Mobile Layout: 480px */
@@ -823,20 +846,19 @@ body.winners #header {
width: 480px;
}
- .recent section {
+ #social {
margin: -10px 0px 40px 0px;
}
- .recent section#social {
+ #social {
text-align: left;
}
- .recent section .social-share {
- display: block;
- float: right;
+ .social-share {
+ white-space: nowrap;
}
- .recent section#social h3 {
+ #social h3 {
padding: 0px;
}
@@ -877,7 +899,7 @@ body.winners #header {
background-image: url('../img/sub-curtains-mobile.png');
height: 116px;
}
-
+
.winners #header {
background-image: none;
}
@@ -929,7 +951,7 @@ body.winners #header {
height: 225px;
}
- .recent section .social-share {
+ .social-share {
background-position: -10px;
font-size: 1px;
margin-right: 0px;
@@ -939,15 +961,15 @@ body.winners #header {
width: auto;
}
- .recent section .social-share.share-facebook {
+ .social-share.share-facebook {
background-position: -279px 50%;
}
- .recent section .social-share.share-tumblr {
+ .social-share.share-tumblr {
background-position: -140px 50%;
}
- .recent section .social-share.share-flickr {
+ .social-share.share-flickr {
background-position: -435px 50%;
}
@@ -955,16 +977,16 @@ body.winners #header {
clear: both;
text-align: left;
}
-
+
#nav-sections {
width: 532px;
}
-
- #nav-sections.fixed {
+
+ #nav-sections.fixed {
width: 532px;
margin-left: -48px;
}
-
+
.category ul {
list-style: none;
width: 100%;
@@ -1012,7 +1034,7 @@ body.winners #header {
width: 252px;
}
- .recent section .social-share {
+ .social-share {
display: block;
float: left;
margin-top: 3px;
@@ -1039,7 +1061,7 @@ body.winners #header {
background-image: url('../img/sub-curtains-mobile.png');
height: 116px;
}
-
+
.winners #header {
background-image: none;
}
@@ -1113,7 +1135,7 @@ body.winners #header {
height: 160px;
}
- .recent section .social-share {
+ .social-share {
background-position: -10px;
font-size: 1px;
margin-right: 0px;
@@ -1123,15 +1145,15 @@ body.winners #header {
width: auto;
}
- .recent section .social-share.share-facebook {
+ .social-share.share-facebook {
background-position: -279px 50%;
}
- .recent section .social-share.share-tumblr {
+ .social-share.share-tumblr {
background-position: -140px 50%;
}
- .recent section .social-share.share-flickr {
+ .social-share.share-flickr {
background-position: -435px 50%;
}
@@ -1139,23 +1161,26 @@ body.winners #header {
width: 255px;
}
- .recent section {
+ #social {
clear: both;
display: block;
+ height: 24px;
+ line-height: 24px;
margin: 10px 0px 25px;
- padding: 0px 0px 60px;
+ padding: 0px 0px 80px;
text-align: center;
+ whitespace: normal;
}
.download-firefox {
display: none;
}
-
+
.winners .winners-head {
background: transparent none;
min-height: 0;
}
-
+
.winners .winners-head h1 {
font-size: 48px;
padding: 0;
@@ -1172,7 +1197,7 @@ body.form {
background-image: url('../img/grey-bg.jpg');
}
-body.secondary.recent {
+body.secondary.recent.closed {
background-color: #000;
background-image: url('../img/curtains-contest-closed.png');
background-repeat: repeat-x;
@@ -1771,4 +1796,4 @@ p.form-errors {
float: left;
padding-top: 30px;
width: 100%;
-}
+}
View
48 media/js/winners.js
@@ -0,0 +1,48 @@
+(function ($) {
+ var $window = $(window);
+ var $content = $('.content-wrapper');
+ var $nav = $('#nav-sections');
+ var navTop = $nav.offset();
+ var navHeight = $nav.height() + 24;
+ var fixed = false;
+ var didScroll = false;
+
+ $window.scroll(function() {
+ didScroll = true;
+ });
+
+ function adjustScrollbar() {
+ if (didScroll) {
+ didScroll = false;
+ var scrollTop = $window.scrollTop();
+
+ if (scrollTop >= navTop.top) {
+ if (!fixed) {
+ fixed = true;
+ $nav.addClass("fixed");
+ $content.css({ 'padding-top': navHeight + 24 });
+ }
+ } else {
+ if (fixed) {
+ fixed = false;
+ $nav.removeClass("fixed");
+ $content.css({ 'padding-top': '0' });
+ }
+ }
+ }
+ };
+
+ // Check for an adjusted scrollbar every 250ms.
+ setInterval(adjustScrollbar, 250);
+
+ // Bind scrolling to linked element.
+ $window.on('click', '#nav-sections a', function(e) {
+ e.preventDefault();
+
+ // Extract the target element's ID from the link's href.
+ var target = $(this).attr("href").hash;
+ $('html, body').animate({
+ scrollTop: $(target).offset().top-navHeight
+ }, 1000);
+ });
+})(jQuery);
View
2  requirements/compiled.txt
@@ -1 +1,3 @@
-r ../vendor/src/funfactory/funfactory/requirements/compiled.txt
+
+PIL
View
2  requirements/prod.txt
@@ -8,3 +8,5 @@ django-statsd-mozilla==0.2.1
# pyes 0.15, other versions... not so great.
-e git://github.com/aparo/pyes.git@27d00eac9030cc9c4dfce9231ad1094f1470a3ca#egg=pyes
-e git://github.com/jbalogh/django-cache-machine.git#egg=django-cache-machine
+
+django-waffle
2  vendor
@@ -1 +1 @@
-Subproject commit aed0336c1020ba42f11b9f80d1149a11d8e82d21
+Subproject commit e22c58091674b92252f87742af16a22c92231c58
1  vendor-local/src/django-waffle
@@ -0,0 +1 @@
+Subproject commit acc8e4adb41e7713be9778460fc3e99e034b7511
View
1  vendor-local/vendor.pth
@@ -3,6 +3,7 @@ src/django-cache-machine
src/django-csp
src/django-south
src/django-statsd
+src/django-waffle
src/elasticutils
src/happyforms
src/pyes
Please sign in to comment.
Something went wrong with that request. Please try again.