From 5e0aa075d1e4729b96a584ffc306bb2fca0caef5 Mon Sep 17 00:00:00 2001 From: Evert Date: Fri, 10 Nov 2017 15:55:39 +0200 Subject: [PATCH 01/15] Show - Index Page, CSS --- .editorconfig | 12 ++++++ EpisodesCommunity/urls.py | 1 + LandingPage/static/css/style.css | 66 ++++++++++++++++++++++++++++++++ Show/templates/show.html | 40 +++++++++++++++++++ Show/urls.py | 23 +++++++++++ Show/views.py | 20 ++++++++++ 6 files changed, 162 insertions(+) create mode 100644 .editorconfig create mode 100644 Show/templates/show.html create mode 100644 Show/urls.py diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..efb1e94 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true + +[*.py] +charset = utf-8 +indent_style = space +indent_size = 4 diff --git a/EpisodesCommunity/urls.py b/EpisodesCommunity/urls.py index e7a72a8..8676f12 100644 --- a/EpisodesCommunity/urls.py +++ b/EpisodesCommunity/urls.py @@ -20,5 +20,6 @@ from django.conf.urls.static import static urlpatterns = [ url(r'^admin/', admin.site.urls), + url(r'^show/(?P\w{1,5})/', include('Show.urls')), url(r'^', include('LandingPage.urls')) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/LandingPage/static/css/style.css b/LandingPage/static/css/style.css index af1df3c..1adfa30 100644 --- a/LandingPage/static/css/style.css +++ b/LandingPage/static/css/style.css @@ -59,6 +59,72 @@ body { width: 20%; float: right; } +section.show-details { + position: relative; +} +.show-details .banner { + position: absolute; + width: 100%; + height: 100%; + filter: blur(4px); + background-position: center center; + background-size: cover; + z-index: -1; +} +.show-details .banner-cover { + overflow: auto; +} +.show-details .artwork { + width: 182px; + margin: 15px; + float: left; +} +.show-details .details { + margin-left: 220px; + margin-right: 10px; + margin-bottom: 10px; + margin-top: 10px; + display: block; + min-height: 260px; + overflow: hidden; + font-size: 150%; + background-color: #dadada38; + padding: 10px; +} +.show-details .details h1 { + margin: 0; + font-size: 200%; +} +.show-details .details .description { + display: inline-grid; + width: 80%; +} +.show-details .details .data { + display: inline-grid; + text-align: right; +} +.show-details .stats .param { + color: #a2a2a2; +} +section.seasons { + min-height: 100vh; + padding: 25px; +} +.season-name { + padding: 6px; + font-size: 180%; + background-color: #e8e8e8; +} +a.episode { + padding: 10px; + display: block; + color: #000; + text-decoration: none; + background-color: #f7f7f7; +} +a.episode:nth-child(even) { + background-color: #fbfbfb; +} @media all and (max-width: 800px) { .logo { font-size: 5vw !important; diff --git a/Show/templates/show.html b/Show/templates/show.html new file mode 100644 index 0000000..64548da --- /dev/null +++ b/Show/templates/show.html @@ -0,0 +1,40 @@ +{% extends "base.html" %} +{% block content %} +
+ + +
+
+ {% for season in seasons %} +
+
{% if season.name %}{{season.number}} - {{season.name}}{% else %}Season {{season.number}}{%endif%}
+
+ {% for episode in episodes %} + {% if episode.season == season %} + {{episode.episode}} - {{episode.name}} + {% endif %} + {% endfor %} +
+
+ {% endfor %} +
+{% endblock %} diff --git a/Show/urls.py b/Show/urls.py new file mode 100644 index 0000000..aa3a679 --- /dev/null +++ b/Show/urls.py @@ -0,0 +1,23 @@ +"""Show URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.11/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" + +from django.conf import settings +from django.conf.urls import url, include +from . import views + +urlpatterns = [ + url(r'^', views.Index.as_view()) +] diff --git a/Show/views.py b/Show/views.py index 91ea44a..0f208f5 100644 --- a/Show/views.py +++ b/Show/views.py @@ -1,3 +1,23 @@ from django.shortcuts import render +from django.shortcuts import render +from django.views import View +from django.views.generic.base import TemplateView +from django.conf import settings +from django.http import HttpResponse +from django.http import HttpResponseRedirect + +from LandingPage.models import Show +from LandingPage.models import Season +from LandingPage.models import Episode # Create your views here. + +class Index (TemplateView): + template_name = "show.html" + + def get_context_data(self, abbreviation, **kwargs): + ctx = super().get_context_data() + ctx['show'] = Show.objects.filter(abbr=abbreviation).first() + ctx['seasons'] = Season.objects.filter(show=ctx['show']) + ctx['episodes'] = Episode.objects.filter(show=ctx['show']) + return ctx From f6895e7d2518e40d34b379b50b4b7490626332c4 Mon Sep 17 00:00:00 2001 From: Evert Date: Fri, 10 Nov 2017 17:21:21 +0200 Subject: [PATCH 02/15] Show - Added Submissions Page --- LandingPage/static/css/style.css | 83 ++++++++++++++++++++++++-------- Show/templates/episode.html | 32 ++++++++++++ Show/templates/show.html | 9 ++-- Show/urls.py | 3 +- Show/views.py | 28 ++++++++++- 5 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 Show/templates/episode.html diff --git a/LandingPage/static/css/style.css b/LandingPage/static/css/style.css index 1adfa30..307e516 100644 --- a/LandingPage/static/css/style.css +++ b/LandingPage/static/css/style.css @@ -4,6 +4,15 @@ body { margin: 0; padding: 0; } +.button, input[type="submit"], button { + display: inline-block; + padding: 5px 10px; + background-color: #fdfdfd; + border: 1px solid #ddd; + border-radius: 5px; + text-decoration: none; + color: #000; +} .unibar { padding: 20px; border-bottom: 1px solid #ddd; @@ -96,35 +105,71 @@ section.show-details { font-size: 200%; } .show-details .details .description { - display: inline-grid; width: 80%; } -.show-details .details .data { - display: inline-grid; - text-align: right; -} -.show-details .stats .param { - color: #a2a2a2; -} -section.seasons { - min-height: 100vh; - padding: 25px; +section.seasons, section.submissions { + min-height: 100vh; + padding: 25px; } .season-name { - padding: 6px; - font-size: 180%; - background-color: #e8e8e8; + padding: 6px; + font-size: 180%; + background-color: #e8e8e8; } a.episode { - padding: 10px; - display: block; - color: #000; - text-decoration: none; - background-color: #f7f7f7; + padding: 10px; + display: block; + color: #000; + text-decoration: none; + background-color: #f7f7f7; } a.episode:nth-child(even) { background-color: #fbfbfb; } +a.episode .submission_cnt { + float: right; + color: #949494; +} +.submission-list .submission { + background-color: #f9f9f9; +} +.submission-list .submission:nth-child(even) { + background-color: #ececec; +} +.submission { + padding: 10px; +} +.submission a { + font-size: 180%; + text-decoration: none; + color: #191919; + font-style: italic; +} +.vote-btns { + float: right; +} +.vote-positive, .vote-negative { + padding: 10px; + display: inline-block; + min-width: 20px; + text-align: center; + border-radius: 5px; + font-weight: bold; +} +.vote-positive { + background-color: #a4ffa7; + color: #008005; +} +.vote-negative { + background-color: #ffa6a6; + color: #ab0000; +} +.submission.buried .vote-btns{ + opacity: 0.5; +} +.submission.buried a { + color: #d2d2d2; +} @media all and (max-width: 800px) { .logo { font-size: 5vw !important; diff --git a/Show/templates/episode.html b/Show/templates/episode.html new file mode 100644 index 0000000..e3b5d60 --- /dev/null +++ b/Show/templates/episode.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% block content %} +
+ + +
+
+ << Show Index +

Watch {{episode.name}} From

+
+ {% for sbm in submissions %} +
+  {{sbm.url}} +
+
 {{sbm.positives}}
+
 {{sbm.negatives}}
+
+
+ {% endfor %} +
+
+{% endblock %} diff --git a/Show/templates/show.html b/Show/templates/show.html index 64548da..8edd791 100644 --- a/Show/templates/show.html +++ b/Show/templates/show.html @@ -24,14 +24,15 @@
+

Watch Now

{% for season in seasons %}
{% if season.name %}{{season.number}} - {{season.name}}{% else %}Season {{season.number}}{%endif%}
- {% for episode in episodes %} - {% if episode.season == season %} - {{episode.episode}} - {{episode.name}} - {% endif %} + {% for episode in season.episodes.all %} + {{episode.episode}} - {{episode.name}} + {{episode.submissions.all|length}} Available Links + {% endfor %}
diff --git a/Show/urls.py b/Show/urls.py index aa3a679..504224c 100644 --- a/Show/urls.py +++ b/Show/urls.py @@ -19,5 +19,6 @@ from django.conf.urls import url, include from . import views urlpatterns = [ - url(r'^', views.Index.as_view()) + url(r'^$', views.IndexView.as_view()), + url(r'^episode/(?P\d{1,4})/(?P\d{1,4})/?$', views.EpisodeView.as_view()) ] diff --git a/Show/views.py b/Show/views.py index 0f208f5..ad83970 100644 --- a/Show/views.py +++ b/Show/views.py @@ -9,15 +9,39 @@ from django.http import HttpResponseRedirect from LandingPage.models import Show from LandingPage.models import Season from LandingPage.models import Episode +from LandingPage.models import Submission # Create your views here. -class Index (TemplateView): +class IndexView(TemplateView): template_name = "show.html" def get_context_data(self, abbreviation, **kwargs): ctx = super().get_context_data() ctx['show'] = Show.objects.filter(abbr=abbreviation).first() ctx['seasons'] = Season.objects.filter(show=ctx['show']) - ctx['episodes'] = Episode.objects.filter(show=ctx['show']) + ctx['episodes'] = Episode.objects.filter(show=ctx['show']).count() + return ctx + +class EpisodeView(TemplateView): + template_name = "episode.html" + + def get_context_data(self, abbreviation, season, episode, **kwargs): + ctx = super().get_context_data() + ctx['show'] = Show.objects.filter(abbr=abbreviation).first() + ctx['episode'] = Episode.objects.filter(show=ctx['show'],episode=episode).first() + + if not ctx['episode']: + return ctx + + # If you're smarter than me, maybe you can compress the next 8 lines into fewer ones by some django magic I'm not aware of + submissions = ctx['episode'].submissions.all() + + for sbm in submissions: + sbm.positives = sbm.votes.filter(positive=True).count() + sbm.negatives = sbm.votes.count() - sbm.positives + + # sorts by "score", TODO: less bullshit + ctx['submissions'] = reversed(sorted(submissions, key=lambda x: x.positives - x.negatives)) + return ctx From 4adab93c3a3763632645050684ddb9c5e6b77d0b Mon Sep 17 00:00:00 2001 From: Evert Date: Fri, 10 Nov 2017 17:47:45 +0200 Subject: [PATCH 03/15] Show - Show empty message for no submitted links --- LandingPage/static/css/style.css | 8 +++----- LandingPage/templates/landing_page.html | 2 +- Show/templates/episode.html | 14 ++++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/LandingPage/static/css/style.css b/LandingPage/static/css/style.css index 307e516..f8c6dba 100644 --- a/LandingPage/static/css/style.css +++ b/LandingPage/static/css/style.css @@ -155,6 +155,7 @@ a.episode .submission_cnt { text-align: center; border-radius: 5px; font-weight: bold; + cursor: pointer; } .vote-positive { background-color: #a4ffa7; @@ -164,11 +165,8 @@ a.episode .submission_cnt { background-color: #ffa6a6; color: #ab0000; } -.submission.buried .vote-btns{ - opacity: 0.5; -} -.submission.buried a { - color: #d2d2d2; +.submission-list .submission.buried { + opacity: 0.3; } @media all and (max-width: 800px) { .logo { diff --git a/LandingPage/templates/landing_page.html b/LandingPage/templates/landing_page.html index de1e5bd..172e3d9 100644 --- a/LandingPage/templates/landing_page.html +++ b/LandingPage/templates/landing_page.html @@ -25,7 +25,7 @@
{% if not recent %} Nothing to show {% endif %} {% for show in recent %} - + {{show.name}} diff --git a/Show/templates/episode.html b/Show/templates/episode.html index e3b5d60..b50f1cf 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -19,13 +19,15 @@

Watch {{episode.name}} From

{% for sbm in submissions %} -
-  {{sbm.url}} -
-
 {{sbm.positives}}
-
 {{sbm.negatives}}
-
+
+  {{sbm.url}} +
+
 {{sbm.positives}}
+
 {{sbm.negatives}}
+
+ {% empty %} +

Nobody has submitted any links yet.

{% endfor %}
From 94b54a0ef2aa77cf113a20d09d75fe178339a34a Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 10:03:06 +0200 Subject: [PATCH 04/15] Show - Use .annotate for submissions with votes and their ordering --- Show/views.py | 63 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/Show/views.py b/Show/views.py index ad83970..2c9d158 100644 --- a/Show/views.py +++ b/Show/views.py @@ -3,8 +3,10 @@ from django.shortcuts import render from django.views import View from django.views.generic.base import TemplateView from django.conf import settings +from django.http import Http404 from django.http import HttpResponse from django.http import HttpResponseRedirect +from django.db.models import Case, When, Value, IntegerField, Count, F from LandingPage.models import Show from LandingPage.models import Season @@ -13,35 +15,66 @@ from LandingPage.models import Submission # Create your views here. +# Index page of a show class IndexView(TemplateView): template_name = "show.html" def get_context_data(self, abbreviation, **kwargs): ctx = super().get_context_data() - ctx['show'] = Show.objects.filter(abbr=abbreviation).first() - ctx['seasons'] = Season.objects.filter(show=ctx['show']) - ctx['episodes'] = Episode.objects.filter(show=ctx['show']).count() + + # Get show by abbreviation, add episode count to the show and return only the first object + show = Show.objects.filter(abbr=abbreviation).annotate(episode_count=Count('episodes')).first() + + # 404 + if not show: + raise Http404("Show does not exist") + + # Get all seasons of the show and annotate episode counts onto them + seasons = show.seasons.all().annotate(episode_count=Count('episodes')) + + # Add fields to context + ctx['show'] = show + ctx['seasons'] = seasons + return ctx +# Episodes page of a show class EpisodeView(TemplateView): template_name = "episode.html" def get_context_data(self, abbreviation, season, episode, **kwargs): ctx = super().get_context_data() - ctx['show'] = Show.objects.filter(abbr=abbreviation).first() - ctx['episode'] = Episode.objects.filter(show=ctx['show'],episode=episode).first() + + # Get show by abbreviation + show = Show.objects.filter(abbr=abbreviation).first() + + # Get episode by season and episode number + episode = Episode.objects.filter(show=show,episode=episode).first() + + # 404's + if not show: + raise Http404("Show does not exist") - if not ctx['episode']: - return ctx + if not episode: + raise Http404("Episode does not exist") - # If you're smarter than me, maybe you can compress the next 8 lines into fewer ones by some django magic I'm not aware of - submissions = ctx['episode'].submissions.all() + # I aknowledge that this is a mess. A functional mess. But a mess nonetheless. Hey, that rhymed! + submissions = episode.submissions.annotate( + positives=Count( + Case( + When( + votes__positive=True, + then=Value(1) + ) + ) + ), + negatives=Count('votes') - F('positives'), + score=F('positives') - F('negatives') + ).order_by('-score') - for sbm in submissions: - sbm.positives = sbm.votes.filter(positive=True).count() - sbm.negatives = sbm.votes.count() - sbm.positives - - # sorts by "score", TODO: less bullshit - ctx['submissions'] = reversed(sorted(submissions, key=lambda x: x.positives - x.negatives)) + # Add fields to context + ctx['show'] = show + ctx['episode'] = episode + ctx['submissions'] = submissions return ctx From 1e868efb72592e1ce2624dd0bb1e4fa9932bb54c Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 10:12:39 +0200 Subject: [PATCH 05/15] Remove those counts because I can just use |length --- Show/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Show/views.py b/Show/views.py index 2c9d158..1646a0c 100644 --- a/Show/views.py +++ b/Show/views.py @@ -23,14 +23,14 @@ class IndexView(TemplateView): ctx = super().get_context_data() # Get show by abbreviation, add episode count to the show and return only the first object - show = Show.objects.filter(abbr=abbreviation).annotate(episode_count=Count('episodes')).first() + show = Show.objects.filter(abbr=abbreviation).first() # 404 if not show: raise Http404("Show does not exist") # Get all seasons of the show and annotate episode counts onto them - seasons = show.seasons.all().annotate(episode_count=Count('episodes')) + seasons = show.seasons.all() # Add fields to context ctx['show'] = show From 528e95fc7beff7243746ad45f2aad177104803a3 Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 11:24:39 +0200 Subject: [PATCH 06/15] Show - Allow submissions to be voted for --- LandingPage/static/css/style.css | 3 +- Show/templates/episode.html | 12 +++++--- Show/urls.py | 3 +- Show/views.py | 47 +++++++++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/LandingPage/static/css/style.css b/LandingPage/static/css/style.css index f8c6dba..5c3ff2b 100644 --- a/LandingPage/static/css/style.css +++ b/LandingPage/static/css/style.css @@ -139,7 +139,7 @@ a.episode .submission_cnt { .submission { padding: 10px; } -.submission a { +.submission a.link { font-size: 180%; text-decoration: none; color: #191919; @@ -156,6 +156,7 @@ a.episode .submission_cnt { border-radius: 5px; font-weight: bold; cursor: pointer; + text-decoration: none; } .vote-positive { background-color: #a4ffa7; diff --git a/Show/templates/episode.html b/Show/templates/episode.html index b50f1cf..3e475a4 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -20,10 +20,14 @@
{% for sbm in submissions %}
-  {{sbm.url}} -
-
 {{sbm.positives}}
-
 {{sbm.negatives}}
+  {{sbm.url}} +
{% empty %} diff --git a/Show/urls.py b/Show/urls.py index 504224c..2bfc217 100644 --- a/Show/urls.py +++ b/Show/urls.py @@ -20,5 +20,6 @@ from . import views urlpatterns = [ url(r'^$', views.IndexView.as_view()), - url(r'^episode/(?P\d{1,4})/(?P\d{1,4})/?$', views.EpisodeView.as_view()) + url(r'^episode/(?P\d{1,4})/(?P\d{1,4})/?$', views.EpisodeView.as_view()), + url(r'^vote/(?P\d+)/(?P[0-1])/?$', views.SubmissionVoteSubmit.as_view()) ] diff --git a/Show/views.py b/Show/views.py index 1646a0c..3512549 100644 --- a/Show/views.py +++ b/Show/views.py @@ -8,10 +8,11 @@ from django.http import HttpResponse from django.http import HttpResponseRedirect from django.db.models import Case, When, Value, IntegerField, Count, F +from LandingPage.models import User from LandingPage.models import Show from LandingPage.models import Season from LandingPage.models import Episode -from LandingPage.models import Submission +from LandingPage.models import Submission, SubmissionVote # Create your views here. @@ -78,3 +79,47 @@ class EpisodeView(TemplateView): ctx['submissions'] = submissions return ctx + +# Vote request +# /show/{{abbr}}/vote/{{submission id}}/{{positive == 1}} +class SubmissionVoteSubmit(View): + def get (self, req, abbreviation, subid, positive): + # Check for login status + if not req.session['user_id']: + r = HttpResponse('

Error

You need to be logged in to vote. Please log in

') + r.status = 400 + return r + + user = User.objects.get(user_id=req.session['user_id']) + + # Get the submission from the database + submission = Submission.objects.filter(id=subid).first() + + # 404 + if not submission: + raise Http404("Submission does not exist") + + # Prevent voting for own submission + if submission.user == user: + r = HttpResponse('

Error

You cannot vote for your own submission.

') + r.status = 400 + return r + + # Allow changing a vote from positive to negative or vice-versa. Delete vote if its a re-vote + vote = submission.votes.filter(user=user,submission__id=submission.id).first() + if vote: + if not vote.positive == (int(positive) == 1): + vote.positive = int(positive) == 1 + vote.save() + else: + vote.delete() + else: + new_vote = SubmissionVote( + user=user, + submission=submission, + positive=int(positive) == 1 + ) + new_vote.save() + + return HttpResponseRedirect('/show/%s/episode/%d/%d'%(abbreviation, submission.episode.season.number, submission.episode.episode)) + From c3eff9f88a85ec947bda60e9a3f541f61ee5e3c4 Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 11:26:26 +0200 Subject: [PATCH 07/15] Show - Convert positive to a boolean --- Show/views.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Show/views.py b/Show/views.py index 3512549..d8a5afb 100644 --- a/Show/views.py +++ b/Show/views.py @@ -84,6 +84,9 @@ class EpisodeView(TemplateView): # /show/{{abbr}}/vote/{{submission id}}/{{positive == 1}} class SubmissionVoteSubmit(View): def get (self, req, abbreviation, subid, positive): + # Convert positive parameter into a boolean + pos_bool = int(positive) == 1 + # Check for login status if not req.session['user_id']: r = HttpResponse('

Error

You need to be logged in to vote. Please log in

') @@ -108,8 +111,8 @@ class SubmissionVoteSubmit(View): # Allow changing a vote from positive to negative or vice-versa. Delete vote if its a re-vote vote = submission.votes.filter(user=user,submission__id=submission.id).first() if vote: - if not vote.positive == (int(positive) == 1): - vote.positive = int(positive) == 1 + if not vote.positive == pos_bool: + vote.positive = pos_bool vote.save() else: vote.delete() @@ -117,7 +120,7 @@ class SubmissionVoteSubmit(View): new_vote = SubmissionVote( user=user, submission=submission, - positive=int(positive) == 1 + positive=pos_bool ) new_vote.save() From 1f71c26fe780f93079a93e0beca6aff9bc6b9d9e Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 12:41:41 +0200 Subject: [PATCH 08/15] conserve lines, fix issue --- Show/views.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Show/views.py b/Show/views.py index d8a5afb..e6e7a02 100644 --- a/Show/views.py +++ b/Show/views.py @@ -88,10 +88,8 @@ class SubmissionVoteSubmit(View): pos_bool = int(positive) == 1 # Check for login status - if not req.session['user_id']: - r = HttpResponse('

Error

You need to be logged in to vote. Please log in

') - r.status = 400 - return r + if not 'user_id' in req.session: + return HttpResponse('

Error

You need to be logged in to vote. Please log in

', status=400) user = User.objects.get(user_id=req.session['user_id']) @@ -104,9 +102,7 @@ class SubmissionVoteSubmit(View): # Prevent voting for own submission if submission.user == user: - r = HttpResponse('

Error

You cannot vote for your own submission.

') - r.status = 400 - return r + return HttpResponse('

Error

You cannot vote for your own submission.

', status=400) # Allow changing a vote from positive to negative or vice-versa. Delete vote if its a re-vote vote = submission.votes.filter(user=user,submission__id=submission.id).first() From c6672da6c63bf2b814f78a8ac8372d135ef69426 Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 12:53:25 +0200 Subject: [PATCH 09/15] slugify episode name into url --- Show/templates/show.html | 2 +- Show/urls.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Show/templates/show.html b/Show/templates/show.html index 8edd791..e9b052c 100644 --- a/Show/templates/show.html +++ b/Show/templates/show.html @@ -30,7 +30,7 @@
{% if season.name %}{{season.number}} - {{season.name}}{% else %}Season {{season.number}}{%endif%}
{% for episode in season.episodes.all %} - {{episode.episode}} - {{episode.name}} + {{episode.episode}} - {{episode.name}} {{episode.submissions.all|length}} Available Links {% endfor %} diff --git a/Show/urls.py b/Show/urls.py index 2bfc217..2817b0e 100644 --- a/Show/urls.py +++ b/Show/urls.py @@ -20,6 +20,6 @@ from . import views urlpatterns = [ url(r'^$', views.IndexView.as_view()), - url(r'^episode/(?P\d{1,4})/(?P\d{1,4})/?$', views.EpisodeView.as_view()), + url(r'^episode/(?P\d{1,4})/(?P\d{1,4})(-[\w-]+)?/?$', views.EpisodeView.as_view()), url(r'^vote/(?P\d+)/(?P[0-1])/?$', views.SubmissionVoteSubmit.as_view()) ] From f13c412f85b61e81a6d7f99621486af64a82d7f0 Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 13:30:16 +0200 Subject: [PATCH 10/15] Show - add page titles --- Show/templates/episode.html | 3 +++ Show/templates/show.html | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Show/templates/episode.html b/Show/templates/episode.html index 3e475a4..70a5109 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -1,4 +1,7 @@ {% extends "base.html" %} +{% block title %} + Episode "{{episode.name}}" - S{{episode.season.number}}E{{episode.episode}} - {{show.name}} - Episodes.Community +{% endblock %} {% block content %}
diff --git a/Show/templates/show.html b/Show/templates/show.html index e9b052c..8b66ddb 100644 --- a/Show/templates/show.html +++ b/Show/templates/show.html @@ -1,4 +1,7 @@ {% extends "base.html" %} +{% block title %} + Watch {{show.name}} Now - on Episodes.Community! +{% endblock %} {% block content %}
From a8d2961a7996ac20576e635e43409b8f7b35f085 Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 14:57:52 +0200 Subject: [PATCH 11/15] Show - Add episode link submissions --- LandingPage/static/css/style.css | 30 +++++++++++++++ Show/forms.py | 11 ++++++ Show/templates/episode.html | 5 ++- Show/templates/submit.html | 34 ++++++++++++++++ Show/urls.py | 1 + Show/views.py | 66 +++++++++++++++++++++++++++++++- 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 Show/forms.py create mode 100644 Show/templates/submit.html diff --git a/LandingPage/static/css/style.css b/LandingPage/static/css/style.css index 5c3ff2b..e421c70 100644 --- a/LandingPage/static/css/style.css +++ b/LandingPage/static/css/style.css @@ -13,6 +13,29 @@ body { text-decoration: none; color: #000; } +input[type="submit"] { + font-size: 120%; +} +label { + width: 200px; + display: block; +} +input[type=text], input:not([type=submit]) { + padding: 5px; + font-size: 120%; + width: 280px; + border-radius: 5px; + border: 1px solid #b3b3b3; + background-color: #ffffff; + box-shadow: inset 2px 2px 5px #ddd; +} +.helptext { + display: block; + margin-bottom: 10px; + font-style: italic; + font-size: 80%; + cursor: help; +} .unibar { padding: 20px; border-bottom: 1px solid #ddd; @@ -169,6 +192,13 @@ a.episode .submission_cnt { .submission-list .submission.buried { opacity: 0.3; } +.message.error { + width: fit-content; + padding: 10px; + background-color: #ffcaca; + border: 1px solid #b10000; + margin: 5px 0; +} @media all and (max-width: 800px) { .logo { font-size: 5vw !important; diff --git a/Show/forms.py b/Show/forms.py new file mode 100644 index 0000000..163cff9 --- /dev/null +++ b/Show/forms.py @@ -0,0 +1,11 @@ +from django import forms +from LandingPage.models import Submission + +class SubmissionForm(forms.ModelForm): + class Meta(): + model = Submission + fields = ('url','tags',) + help_texts = { + 'url': 'URL to your episode', + 'tags': 'Describe your link. Comma-separated list of keywords' + } diff --git a/Show/templates/episode.html b/Show/templates/episode.html index 70a5109..9a28c22 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -18,7 +18,10 @@
- << Show Index +  Show Index + {% if request.session.user_id %} +  Submit New Link + {% endif %}

Watch {{episode.name}} From

{% for sbm in submissions %} diff --git a/Show/templates/submit.html b/Show/templates/submit.html new file mode 100644 index 0000000..d34a925 --- /dev/null +++ b/Show/templates/submit.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% block title %} + Episode "{{episode.name}}" - S{{episode.season.number}}E{{episode.episode}} - {{show.name}} - Episodes.Community +{% endblock %} +{% block content %} +
+ + +
+
+  Show Index + Back to Episode +

Submit a link

+ {% if error %} +
{{error}}
+ {% endif %} +
+ {% csrf_token %} + {{ form }} + +
+
+
+{% endblock %} diff --git a/Show/urls.py b/Show/urls.py index 2817b0e..10095fa 100644 --- a/Show/urls.py +++ b/Show/urls.py @@ -21,5 +21,6 @@ from . import views urlpatterns = [ url(r'^$', views.IndexView.as_view()), url(r'^episode/(?P\d{1,4})/(?P\d{1,4})(-[\w-]+)?/?$', views.EpisodeView.as_view()), + url(r'^episode/(?P\d{1,4})/(?P\d{1,4})(-[\w-]+)?/submit$', views.SubmissionForm), url(r'^vote/(?P\d+)/(?P[0-1])/?$', views.SubmissionVoteSubmit.as_view()) ] diff --git a/Show/views.py b/Show/views.py index e6e7a02..9e91303 100644 --- a/Show/views.py +++ b/Show/views.py @@ -1,4 +1,4 @@ -from django.shortcuts import render +from django.template import RequestContext from django.shortcuts import render from django.views import View from django.views.generic.base import TemplateView @@ -14,6 +14,10 @@ from LandingPage.models import Season from LandingPage.models import Episode from LandingPage.models import Submission, SubmissionVote +from . import forms + +import datetime + # Create your views here. # Index page of a show @@ -50,7 +54,7 @@ class EpisodeView(TemplateView): show = Show.objects.filter(abbr=abbreviation).first() # Get episode by season and episode number - episode = Episode.objects.filter(show=show,episode=episode).first() + episode = Episode.objects.filter(show=show,season__number=season,episode=episode).first() # 404's if not show: @@ -80,6 +84,64 @@ class EpisodeView(TemplateView): return ctx +# Submission form GET and POST +def SubmissionForm(req, abbreviation, season, episode): + show = Show.objects.get(abbr=abbreviation) + episode = Episode.objects.filter(show=show,season__number=season,episode=episode).first() + + # Check for login status + if not 'user_id' in req.session: + return HttpResponse('

Error

You need to be logged in to submit. Please log in

', status=400) + + user = User.objects.get(user_id=req.session['user_id']) + + # 404's + if not show: + raise Http404("Show does not exist") + + if not episode: + raise Http404("Episode does not exist") + + form = forms.SubmissionForm() + + # Request context + ctx = { + 'form': form, + 'show': show, + 'episode': episode + } + + # Handle POST + if req.method == 'POST': + form = forms.SubmissionForm(req.POST) + ctx['form'] = form + + if form.is_valid(): + form_data = form.cleaned_data + + # Check if the URL has already been submitted + if Submission.objects.filter(episode=episode,url=form_data['url']).count() > 0: + ctx['error'] = 'This URL has already been submitted!' + return render(req, "submit.html", ctx) + + # Check if there has been a submission by this user for this episode within the last 24 hours + if Submission.objects.filter(user=user,episode=episode,timestamp__gte=datetime.date.today() - datetime.timedelta(hours=24)).count() > 0: + ctx['error'] = 'You can only submit one link for an episode in 24 hours!' + return render(req, "submit.html", ctx) + + # Have to do this because you can't add fields to a form + # If you know a better way of doing this, be my guest + new_submission = form.save(commit=False) + new_submission.user = user + new_submission.episode = episode + new_submission.save() + + return HttpResponseRedirect('/show/%s/episode/%d/%d'%(abbreviation, episode.season.number, episode.episode)) + else: + ctx['error'] = 'Invalid fields!' + + return render(req, "submit.html", ctx) + # Vote request # /show/{{abbr}}/vote/{{submission id}}/{{positive == 1}} class SubmissionVoteSubmit(View): From 576c91a6a8f6ae2028e3cbddce787436249fc32c Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 15:33:27 +0200 Subject: [PATCH 12/15] Show - Add Open Graph meta to episode and show page --- Show/templates/episode.html | 13 +++++++++++++ Show/templates/show.html | 9 +++++++++ Show/templates/submit.html | 2 +- Show/views.py | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Show/templates/episode.html b/Show/templates/episode.html index 9a28c22..1e53526 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -1,7 +1,18 @@ {% extends "base.html" %} + {% block title %} Episode "{{episode.name}}" - S{{episode.season.number}}E{{episode.episode}} - {{show.name}} - Episodes.Community {% endblock %} + +{% block meta %} + {{ block.super }} + + + + + +{% endblock %} + {% block content %}
@@ -21,6 +32,8 @@  Show Index {% if request.session.user_id %}  Submit New Link + {% else %} + Log in to submit a link {% endif %}

Watch {{episode.name}} From

diff --git a/Show/templates/show.html b/Show/templates/show.html index 8b66ddb..e8c46c6 100644 --- a/Show/templates/show.html +++ b/Show/templates/show.html @@ -2,6 +2,15 @@ {% block title %} Watch {{show.name}} Now - on Episodes.Community! {% endblock %} + +{% block meta %} + {{ block.super }} + + + + +{% endblock %} + {% block content %}
diff --git a/Show/templates/submit.html b/Show/templates/submit.html index d34a925..98d285c 100644 --- a/Show/templates/submit.html +++ b/Show/templates/submit.html @@ -1,6 +1,6 @@ {% extends "base.html" %} {% block title %} - Episode "{{episode.name}}" - S{{episode.season.number}}E{{episode.episode}} - {{show.name}} - Episodes.Community + Submit a link - S{{episode.season.number}}E{{episode.episode}} - {{show.name}} - Episodes.Community {% endblock %} {% block content %}
diff --git a/Show/views.py b/Show/views.py index 9e91303..f3740e9 100644 --- a/Show/views.py +++ b/Show/views.py @@ -63,7 +63,7 @@ class EpisodeView(TemplateView): if not episode: raise Http404("Episode does not exist") - # I aknowledge that this is a mess. A functional mess. But a mess nonetheless. Hey, that rhymed! + # I acknowledge that this is a mess. A functional mess. But a mess nonetheless. Hey, that rhymed! submissions = episode.submissions.annotate( positives=Count( Case( From f07f6f1b46850785196dd86a46b5f1eefa5c322f Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 15:37:36 +0200 Subject: [PATCH 13/15] change banner to artwork --- Show/templates/episode.html | 2 +- Show/templates/show.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Show/templates/episode.html b/Show/templates/episode.html index 1e53526..0b3924d 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -9,7 +9,7 @@ - + {% endblock %} diff --git a/Show/templates/show.html b/Show/templates/show.html index e8c46c6..a4ed4de 100644 --- a/Show/templates/show.html +++ b/Show/templates/show.html @@ -7,7 +7,7 @@ {{ block.super }} - + {% endblock %} From 064406bf89e9a00383d0f5db8df2afce8d6b2334 Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 17:35:21 +0200 Subject: [PATCH 14/15] use datetime.now instead of today --- Show/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Show/views.py b/Show/views.py index f3740e9..1bcc5e3 100644 --- a/Show/views.py +++ b/Show/views.py @@ -125,7 +125,7 @@ def SubmissionForm(req, abbreviation, season, episode): return render(req, "submit.html", ctx) # Check if there has been a submission by this user for this episode within the last 24 hours - if Submission.objects.filter(user=user,episode=episode,timestamp__gte=datetime.date.today() - datetime.timedelta(hours=24)).count() > 0: + if Submission.objects.filter(user=user,episode=episode,timestamp__gte=datetime.datetime.now() - datetime.timedelta(hours=24)).count() > 0: ctx['error'] = 'You can only submit one link for an episode in 24 hours!' return render(req, "submit.html", ctx) From c11a43b7c5e76f3e4edb897e8e828ac5c91fa6bf Mon Sep 17 00:00:00 2001 From: Evert Date: Sat, 11 Nov 2017 20:34:48 +0200 Subject: [PATCH 15/15] Show - Form hack with vote buttons - CSRF protection --- LandingPage/static/css/style.css | 3 +++ Show/templates/episode.html | 18 ++++++++++++------ Show/views.py | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/LandingPage/static/css/style.css b/LandingPage/static/css/style.css index e421c70..045cd4b 100644 --- a/LandingPage/static/css/style.css +++ b/LandingPage/static/css/style.css @@ -181,6 +181,9 @@ a.episode .submission_cnt { cursor: pointer; text-decoration: none; } +.vote-btns form { + display: inline-block; +} .vote-positive { background-color: #a4ffa7; color: #008005; diff --git a/Show/templates/episode.html b/Show/templates/episode.html index 0b3924d..9563ae7 100644 --- a/Show/templates/episode.html +++ b/Show/templates/episode.html @@ -41,12 +41,18 @@
 {{sbm.url}}
- -  {{sbm.positives}} - - -  {{sbm.negatives}} - +
+ {% csrf_token %} + +
+
+ {% csrf_token %} + +
{% empty %} diff --git a/Show/views.py b/Show/views.py index 1bcc5e3..ba23497 100644 --- a/Show/views.py +++ b/Show/views.py @@ -145,7 +145,7 @@ def SubmissionForm(req, abbreviation, season, episode): # Vote request # /show/{{abbr}}/vote/{{submission id}}/{{positive == 1}} class SubmissionVoteSubmit(View): - def get (self, req, abbreviation, subid, positive): + def post (self, req, abbreviation, subid, positive): # Convert positive parameter into a boolean pos_bool = int(positive) == 1