Skip to content

Commit

Permalink
Merge pull request #27 from michigg/25-user-gif-upload
Browse files Browse the repository at this point in the history
WIP: 25 user gif upload
  • Loading branch information
Michael Götz authored Jan 26, 2020
2 parents 1c5276e + 9a34a80 commit bb399e2
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 84 deletions.
1 change: 1 addition & 0 deletions src/core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
path('logout/', auth_views.LogoutView.as_view(), {'next_page': '/'}, name='logout'),
path('admin/', admin.site.urls),
path('', views.home, name="home"),
path('videos/', views.registration_gif, name='gifs'),
path('quote-registration/', views.registration_quote, name="register_quote"),
path('author-registration/', views.registration_author, name="register_author"),
path('api/', include('fachschaftszitat.api.urls')),
Expand Down
3 changes: 2 additions & 1 deletion src/fachschaftszitat/admin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import Quote, Statement, Author
from .models import Quote, Statement, Author, Gif

# Register your models here.
admin.site.register(Quote)
admin.site.register(Statement)
admin.site.register(Author)
admin.site.register(Gif)

UserAdmin.list_display = ('id',) + UserAdmin.list_display
23 changes: 20 additions & 3 deletions src/fachschaftszitat/api/serializer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rest_framework import serializers
from fachschaftszitat.models import Quote, Statement, Author
from django.contrib.auth.models import Group
from fachschaftszitat.models import Quote, Statement, Author, Gif
from django.contrib.auth.models import Group, User


class AuthorSerializer(serializers.ModelSerializer):
Expand All @@ -24,9 +24,26 @@ class Meta:


class QuoteSerializer(serializers.Serializer):
id = serializers.IntegerField()
id = serializers.IntegerField(read_only=True)
timestamp = serializers.DateField()
statements = StatementSerializer(many=True)
owner = GroupSerializer()
is_creator = serializers.BooleanField()
delete_url = serializers.CharField()


class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username')


class GifSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
type = serializers.ChoiceField(choices=Gif.TYPE_CHOICES)
video_url = serializers.URLField()
is_creator = serializers.BooleanField()
delete_url = serializers.CharField()

def create(self, validated_data):
return Gif.objects.create(**validated_data)
2 changes: 2 additions & 0 deletions src/fachschaftszitat/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
path('quote/', views.ApiGetQuotes.as_view(), name='quotes'),
path('quote/<int:pk>/', views.ApiRemoveQuote.as_view(), name='delete-quote'),
path('author/', views.ApiGetAuthors.as_view(), name='authors'),
path('gif/', views.ApiGifs.as_view(), name='gifs'),
path('gif/<int:pk>/', views.ApiGif.as_view(), name='delete-gif'),
]
38 changes: 36 additions & 2 deletions src/fachschaftszitat/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from fachschaftszitat.models import Quote, Author
from .serializer import QuoteSerializer, AuthorSerializer
from fachschaftszitat.models import Quote, Author, Gif
from .serializer import QuoteSerializer, AuthorSerializer, GifSerializer


@permission_classes((IsAuthenticated,))
Expand Down Expand Up @@ -41,6 +41,9 @@ class ApiRemoveQuote(generics.RetrieveUpdateDestroyAPIView):
queryset = Quote.objects.all()
serializer_class = QuoteSerializer

def get_queryset(self):
return Quote.objects.filter(creator=self.request.user)

def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.creator.id != self.request.user.id:
Expand All @@ -49,6 +52,37 @@ def destroy(self, request, *args, **kwargs):
return super().destroy(request, *args, **kwargs)


@permission_classes((IsAuthenticated,))
class ApiGifs(generics.ListAPIView):
serializer_class = GifSerializer

def get_queryset(self):
gifs = Gif.objects.filter(creator=self.request.user)
gifs_wrapper = [
{"id": gif.id,
"video_url": gif.video_url,
"type": gif.type,
"is_creator": gif.creator.id == self.request.user.id,
"delete_url": reverse("fachschaftszitat.api:delete-gif", args=[gif.id])}
for gif in gifs]
return gifs_wrapper


@permission_classes((IsAuthenticated,))
class ApiGif(generics.DestroyAPIView):
serializer_class = GifSerializer

def get_queryset(self):
return Gif.objects.filter(creator=self.request.user)

def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.creator.id != self.request.user.id:
return Response("Wrong user. Cannot delete Gif, because you are not the creator.",
status=status.HTTP_400_BAD_REQUEST)
return super().destroy(request, *args, **kwargs)


class ApiGetAuthors(generics.ListAPIView):
queryset = Author.objects.all()
serializer_class = AuthorSerializer
8 changes: 7 additions & 1 deletion src/fachschaftszitat/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django import forms
from fachschaftszitat.models import Statement, Quote, Author
from fachschaftszitat.models import Statement, Quote, Author, Gif
from django.forms import modelformset_factory
import datetime

Expand Down Expand Up @@ -29,3 +29,9 @@ class AuthorsForm(forms.ModelForm):
class Meta:
model = Author
fields = ['name']


class GifForm(forms.ModelForm):
class Meta:
model = Gif
fields = ['type', 'video_url']
25 changes: 25 additions & 0 deletions src/fachschaftszitat/migrations/0004_gif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.0.2 on 2020-01-20 13:12

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('fachschaftszitat', '0003_quote_creator'),
]

operations = [
migrations.CreateModel(
name='Gif',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(choices=[('ERROR', 'Error'), ('SUCCESS', 'Success')], max_length=8)),
('video_url', models.URLField(unique=True)),
('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
],
),
]
13 changes: 13 additions & 0 deletions src/fachschaftszitat/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@ class Author(models.Model):

def __str__(self):
return self.name


class Gif(models.Model):
ERROR = "ERROR"
SUCCESS = "SUCCESS"
TYPE_CHOICES = [(ERROR, "Error"), (SUCCESS, "Success")]

type = models.CharField(max_length=8, choices=TYPE_CHOICES)
video_url = models.URLField(unique=True)
creator = models.ForeignKey(User, on_delete=models.PROTECT)

def __str__(self):
return f'{self.id} - {self.type} - {self.creator} - {self.video_url}'
49 changes: 41 additions & 8 deletions src/fachschaftszitat/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,30 @@
from django.shortcuts import render

from core.settings import STATICFILES_DIRS, STATIC_URL
from fachschaftszitat.forms import QuoteForm, AuthorsForm, StatementFormset
from fachschaftszitat.models import Quote, Author, Statement
from fachschaftszitat.forms import QuoteForm, AuthorsForm, StatementFormset, GifForm
from fachschaftszitat.models import Quote, Author, Statement, Gif

import logging

logger = logging.getLogger(__name__)


def get_random_sucess_url():
file = random.choice(os.listdir(os.path.join(STATICFILES_DIRS[0], 'images/success')))
return STATIC_URL + 'images/success/' + file
gifs = Gif.objects.filter(type=Gif.SUCCESS)
gif_urls = [gif.video_url for gif in gifs]
files = os.listdir(os.path.join(STATICFILES_DIRS[0], 'images/success'))
file_based_gif_urls = [f'{STATIC_URL}images/success/{file}' for file in files]
gif_urls.extend(file_based_gif_urls)
return random.choice(gif_urls)


def get_random_error_url():
file = random.choice(os.listdir(os.path.join(STATICFILES_DIRS[0], 'images/oops')))
return STATIC_URL + 'images/oops/' + file
gifs = Gif.objects.filter(type=Gif.ERROR)
gif_urls = [gif.video_url for gif in gifs]
files = os.listdir(os.path.join(STATICFILES_DIRS[0], 'images/oops'))
file_based_gif_urls = [f'{STATIC_URL}images/oops/{file}' for file in files]
gif_urls.extend(file_based_gif_urls)
return random.choice(gif_urls)


# Create your views here.
Expand All @@ -46,7 +54,6 @@ def home(request):

@login_required
def registration_quote(request):
logger.error("call")
if request.user.is_authenticated and request.method == 'POST':
quote_form = QuoteForm(request.POST)
statement_form = StatementFormset(request.POST)
Expand All @@ -57,7 +64,7 @@ def registration_quote(request):
pre_save.order_id = order_id
order_id += 1
pre_save.save()
# logger.info("statements_savedee")
# logger.info("statements_savedee")
quote = quote_form.save(commit=False)
quote.creator = request.user
quote.save()
Expand All @@ -75,3 +82,29 @@ def registration_author(request):
form.save()
return JsonResponse({'url': get_random_sucess_url()}, status=201)
return JsonResponse({'url': get_random_error_url()}, status=400)


@login_required
def registration_gif(request):
if request.method == 'POST':
form = GifForm(request.POST)
if form.is_valid():
gif = form.save(commit=False)
if is_video_url_valid(gif.video_url):
gif.creator = request.user
gif.save()
return JsonResponse({'url': get_random_sucess_url()}, status=201)
return JsonResponse({'url': get_random_error_url()}, status=400)
else:
gifs = Gif.objects.filter(creator=request.user)
form = GifForm()
return render(request, 'gif.jinja2', {"form": form, "gifs": gifs})


def is_video_url_valid(url):
url_starts = ["https://media.giphy.com/media/", "https://media.tenor.com/videos/"]
url_ends = [".mp4", "/mp4"]
has_known_url_start = any([url.startswith(url_start) for url_start in url_starts])
has_known_url_end = any([url.endswith(url_end) for url_end in url_ends])

return has_known_url_start and has_known_url_end
16 changes: 13 additions & 3 deletions src/static/home/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ footer {
bottom: 0;
vertical-align: middle;
height: var(--footer-height-y);
line-height: 40px;
line-height: 25px;
}

footer a:link,
Expand Down Expand Up @@ -75,7 +75,7 @@ footer a:active {
:root {
--input-padding-x: .75rem;
--input-padding-y: .6rem;
--footer-height-y: 40px
--footer-height-y: 60px
}


Expand Down Expand Up @@ -164,4 +164,14 @@ footer a:active {
box-shadow: 0 2px 4px rgba(0, 0, 0, .6);
padding: 5px 5px;
margin-bottom: 5px;
}
}


/** **************************************************************************************************************** **/
/** ******** GIFS ******** **/
/** **************************************************************************************************************** **/
.gif-type{
position: absolute;
bottom: 0;
right: 15px;
}
3 changes: 2 additions & 1 deletion src/static/js/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const QUOTES_ENDPOINT = '/api/quote';
const AUTHORS_ENDPOINT = '/api/author';
const QUOTE_FORMULAR = $('#quote-form');
const QUOTE_FORMULAR_CONTENTS = document.getElementById('quote-form').innerHTML;
const AUTHOR_FORMULAR = $("#author-form")
const AUTHOR_FORMULAR = $("#author-form");

let source = document.getElementById("entry-template").innerHTML;
let template = Handlebars.compile(source);
Expand Down Expand Up @@ -106,6 +106,7 @@ function authorSuccessProcess(data) {
AUTHOR_FORMULAR[0].reset();
}


function updateQuotes() {
$.ajax({
url: QUOTES_ENDPOINT,
Expand Down
Loading

0 comments on commit bb399e2

Please sign in to comment.