From 8caf94308146dd717fa851a47377270c9c62bdd6 Mon Sep 17 00:00:00 2001 From: MG Date: Mon, 20 Jan 2020 14:20:28 +0100 Subject: [PATCH 01/16] chore: add new gif model --- src/core/urls.py | 1 + src/fachschaftszitat/forms.py | 8 +- src/fachschaftszitat/migrations/0004_gif.py | 25 ++++++ src/fachschaftszitat/models.py | 10 +++ src/fachschaftszitat/views.py | 21 ++++- src/static/js/form.js | 29 +++++- src/templates/base.jinja2 | 2 +- src/templates/gif.jinja2 | 98 +++++++++++++++++++++ src/templates/macros/util_macros.jinja2 | 15 +++- 9 files changed, 202 insertions(+), 7 deletions(-) create mode 100644 src/fachschaftszitat/migrations/0004_gif.py create mode 100644 src/templates/gif.jinja2 diff --git a/src/core/urls.py b/src/core/urls.py index 1f15ef3..1d4e72c 100644 --- a/src/core/urls.py +++ b/src/core/urls.py @@ -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')), diff --git a/src/fachschaftszitat/forms.py b/src/fachschaftszitat/forms.py index 3575d6f..1e6f11c 100644 --- a/src/fachschaftszitat/forms.py +++ b/src/fachschaftszitat/forms.py @@ -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 @@ -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'] diff --git a/src/fachschaftszitat/migrations/0004_gif.py b/src/fachschaftszitat/migrations/0004_gif.py new file mode 100644 index 0000000..d6bd94a --- /dev/null +++ b/src/fachschaftszitat/migrations/0004_gif.py @@ -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)), + ], + ), + ] diff --git a/src/fachschaftszitat/models.py b/src/fachschaftszitat/models.py index 31f99ac..8902ded 100644 --- a/src/fachschaftszitat/models.py +++ b/src/fachschaftszitat/models.py @@ -47,3 +47,13 @@ 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) diff --git a/src/fachschaftszitat/views.py b/src/fachschaftszitat/views.py index 7fa8f6c..eceb2f5 100644 --- a/src/fachschaftszitat/views.py +++ b/src/fachschaftszitat/views.py @@ -8,8 +8,8 @@ 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 @@ -57,7 +57,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() @@ -75,3 +75,18 @@ 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) + gif.creator = request.user + 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}) diff --git a/src/static/js/form.js b/src/static/js/form.js index 88252d8..8c80e87 100644 --- a/src/static/js/form.js +++ b/src/static/js/form.js @@ -5,9 +5,11 @@ // CONFIG const QUOTES_ENDPOINT = '/api/quote'; const AUTHORS_ENDPOINT = '/api/author'; +const GIFS_ENDPOINT = '/gifs'; +const GIFS_FORMULAR = $("#gif-form"); 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); @@ -106,6 +108,31 @@ function authorSuccessProcess(data) { AUTHOR_FORMULAR[0].reset(); } +GIFS_FORMULAR.submit(function (event) { + console.log("PREVENT"); + event.preventDefault(); + var url = GIFS_FORMULAR.attr('action'); + $.ajax({ + url: url, + type: 'post', + dataType: 'json', + data: GIFS_FORMULAR.serialize(), + success: gifSuccessProcess, + error: displayErrorModal, + }) +}); + +function clearGIFFormular() { + GIFS_FORMULAR.empty(); +} + +function gifSuccessProcess(data) { + // TODO update gifs + // updateQuotes(); + displaySuccessModal(data); + clearGIFFormular(); +} + function updateQuotes() { $.ajax({ url: QUOTES_ENDPOINT, diff --git a/src/templates/base.jinja2 b/src/templates/base.jinja2 index 183457f..a155765 100644 --- a/src/templates/base.jinja2 +++ b/src/templates/base.jinja2 @@ -43,7 +43,7 @@ {{ site_name }}
- Gifs Admin diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 new file mode 100644 index 0000000..2d4175f --- /dev/null +++ b/src/templates/gif.jinja2 @@ -0,0 +1,98 @@ +{% extends 'base.jinja2' %} +{% import 'macros/util_macros.jinja2' as mutils %} + +{% block content %} + {#
#} + {#
#} + {#
#} + {#

Neues Zitat hinzufügen

#} + {# {{ mutils.get_quote_add_form(statement_formset, user_groups, today_date, authors) }}#} + {#
#} + {#
#} +
+
+
+

Info

+

Neue gifs können von den folgenden Seiten hinzugefügt werden:

+ +

Bitte beachtet, dass nur mp4 videos akzeptiert werden können. Deshalb ist es bei Tenor nötig auf MP4 + umzustellen, bevor man die Video Url kopiert. Dies geht am leichtesten mit einem Rechtsklick und der + anschließenden Auswahl von "Grafikadresse kopieren".
Nutzt bei giphy die Copy link Funktion an + den + mp4 link zu gelangen.

+
+
+
+
+
+
+

Neues Gif hinzufügen

+ {{ mutils.get_gif_add_form(form) }} +
+
+
+ {#
#} + {#
#} + {#
#} + {#

Zitate

#} + {# #} + {# #} + {# #} + {# {{ mutils.get_list_headline() }}#} + {#
#} + {#
#} + {# {% raw %}#} + {# #} + {# {% endraw %}#} + {#
#} + {#
#} + {#
#} +{% endblock %} \ No newline at end of file diff --git a/src/templates/macros/util_macros.jinja2 b/src/templates/macros/util_macros.jinja2 index fb9f165..2270ed7 100644 --- a/src/templates/macros/util_macros.jinja2 +++ b/src/templates/macros/util_macros.jinja2 @@ -40,7 +40,7 @@
{% endfor %} @@ -64,6 +64,19 @@ {% endmacro %} +{% macro get_gif_add_form(form) -%} +
+ + + +
+{% endmacro %} + {% macro get_list_headline() -%}
From 191670280144798fd5bf7dd5b652d44514aed7d2 Mon Sep 17 00:00:00 2001 From: MG Date: Mon, 20 Jan 2020 15:14:38 +0100 Subject: [PATCH 02/16] fix: url field name --- src/templates/macros/util_macros.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/templates/macros/util_macros.jinja2 b/src/templates/macros/util_macros.jinja2 index 2270ed7..a5df7d3 100644 --- a/src/templates/macros/util_macros.jinja2 +++ b/src/templates/macros/util_macros.jinja2 @@ -71,7 +71,7 @@ {% endfor %} - From 0a924c1fd8ab75889c409ae1ce39ba2795029615 Mon Sep 17 00:00:00 2001 From: MG Date: Mon, 20 Jan 2020 15:38:23 +0100 Subject: [PATCH 03/16] chore: seperate gif form js --- src/static/js/form.js | 26 -------------- src/static/js/gif_form.js | 74 +++++++++++++++++++++++++++++++++++++++ src/templates/base.jinja2 | 1 + src/templates/gif.jinja2 | 5 +++ 4 files changed, 80 insertions(+), 26 deletions(-) create mode 100644 src/static/js/gif_form.js diff --git a/src/static/js/form.js b/src/static/js/form.js index 8c80e87..17e963a 100644 --- a/src/static/js/form.js +++ b/src/static/js/form.js @@ -5,8 +5,6 @@ // CONFIG const QUOTES_ENDPOINT = '/api/quote'; const AUTHORS_ENDPOINT = '/api/author'; -const GIFS_ENDPOINT = '/gifs'; -const GIFS_FORMULAR = $("#gif-form"); const QUOTE_FORMULAR = $('#quote-form'); const QUOTE_FORMULAR_CONTENTS = document.getElementById('quote-form').innerHTML; const AUTHOR_FORMULAR = $("#author-form"); @@ -108,30 +106,6 @@ function authorSuccessProcess(data) { AUTHOR_FORMULAR[0].reset(); } -GIFS_FORMULAR.submit(function (event) { - console.log("PREVENT"); - event.preventDefault(); - var url = GIFS_FORMULAR.attr('action'); - $.ajax({ - url: url, - type: 'post', - dataType: 'json', - data: GIFS_FORMULAR.serialize(), - success: gifSuccessProcess, - error: displayErrorModal, - }) -}); - -function clearGIFFormular() { - GIFS_FORMULAR.empty(); -} - -function gifSuccessProcess(data) { - // TODO update gifs - // updateQuotes(); - displaySuccessModal(data); - clearGIFFormular(); -} function updateQuotes() { $.ajax({ diff --git a/src/static/js/gif_form.js b/src/static/js/gif_form.js new file mode 100644 index 0000000..cba2faf --- /dev/null +++ b/src/static/js/gif_form.js @@ -0,0 +1,74 @@ +/** + * setup JQuery's AJAX methods to setup CSRF token in the request before sending it off. + * http://stackoverflow.com/questions/5100539/django-csrf-check-failing-with-an-ajax-post-request + */ +// CONFIG +// const GIFS_ENDPOINT = '/gifs'; +const GIFS_FORMULAR = $("#gif-form"); + +// let source = document.getElementById("entry-template").innerHTML; +// let template = Handlebars.compile(source); + +/* jshint esversion: 6 */ + +/** + * Cookie setting for django + * + * @param name cookie name + * @returns {*} + */ +function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== '') { + let cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + let cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +var csrftoken = getCookie('csrftoken'); + +function csrfSafeMethod(method) { + // these HTTP methods do not require CSRF protection + return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); +} + +$.ajaxSetup({ + beforeSend: function (xhr, settings) { + if (!csrfSafeMethod(settings.type) && !this.crossDomain) { + xhr.setRequestHeader("X-CSRFToken", csrftoken); + } + } +}); + +GIFS_FORMULAR.submit(function (event) { + console.log("PREVENT"); + event.preventDefault(); + var url = GIFS_FORMULAR.attr('action'); + $.ajax({ + url: url, + type: 'post', + dataType: 'json', + data: GIFS_FORMULAR.serialize(), + success: gifSuccessProcess, + error: displayErrorModal, + }) +}); + +function clearGIFFormular() { + GIFS_FORMULAR.empty(); +} + +function gifSuccessProcess(data) { + // TODO update gifs + // updateQuotes(); + displaySuccessModal(data); + clearGIFFormular(); +} diff --git a/src/templates/base.jinja2 b/src/templates/base.jinja2 index a155765..e1d0b06 100644 --- a/src/templates/base.jinja2 +++ b/src/templates/base.jinja2 @@ -66,5 +66,6 @@ +{% block js_extra_footer %}{% endblock %} \ No newline at end of file diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index 2d4175f..6448b61 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -95,4 +95,9 @@ {#
#} {#
#} {# #} + + + {% block js_extra_footer %} + + {% endblock %} {% endblock %} \ No newline at end of file From 227bf404978377fbee0c7e8f33d19102bf13c4e8 Mon Sep 17 00:00:00 2001 From: MG Date: Mon, 20 Jan 2020 15:39:01 +0100 Subject: [PATCH 04/16] chore: add choices, activate gif model --- src/fachschaftszitat/admin.py | 3 ++- src/fachschaftszitat/models.py | 3 +++ src/fachschaftszitat/views.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/fachschaftszitat/admin.py b/src/fachschaftszitat/admin.py index 88ff89d..ab38fab 100644 --- a/src/fachschaftszitat/admin.py +++ b/src/fachschaftszitat/admin.py @@ -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 diff --git a/src/fachschaftszitat/models.py b/src/fachschaftszitat/models.py index 8902ded..53102cb 100644 --- a/src/fachschaftszitat/models.py +++ b/src/fachschaftszitat/models.py @@ -57,3 +57,6 @@ class Gif(models.Model): 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.type} - {self.creator} - {self.video_url}' diff --git a/src/fachschaftszitat/views.py b/src/fachschaftszitat/views.py index eceb2f5..5be4211 100644 --- a/src/fachschaftszitat/views.py +++ b/src/fachschaftszitat/views.py @@ -84,6 +84,7 @@ def registration_gif(request): if form.is_valid(): gif = form.save(commit=False) 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: From ac18c314b3d0d72274091d040d539858eddb94f7 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 10:16:36 +0100 Subject: [PATCH 05/16] chore: add new page, add gif formular --- src/fachschaftszitat/api/serializer.py | 22 ++++++++++-- src/fachschaftszitat/api/urls.py | 1 + src/fachschaftszitat/api/views.py | 35 ++++++++++++++++-- src/templates/base.jinja2 | 49 +++++++++++++++++++++++--- src/templates/home.jinja2 | 36 ------------------- 5 files changed, 97 insertions(+), 46 deletions(-) diff --git a/src/fachschaftszitat/api/serializer.py b/src/fachschaftszitat/api/serializer.py index 8d1d310..e5cbde2 100644 --- a/src/fachschaftszitat/api/serializer.py +++ b/src/fachschaftszitat/api/serializer.py @@ -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): @@ -24,9 +24,25 @@ 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() + creator = UserSerializer(read_only=True) + + def create(self, validated_data): + return Gif.objects.create(**validated_data) diff --git a/src/fachschaftszitat/api/urls.py b/src/fachschaftszitat/api/urls.py index 8901342..b91ef30 100644 --- a/src/fachschaftszitat/api/urls.py +++ b/src/fachschaftszitat/api/urls.py @@ -7,4 +7,5 @@ path('quote/', views.ApiGetQuotes.as_view(), name='quotes'), path('quote//', views.ApiRemoveQuote.as_view(), name='delete-quote'), path('author/', views.ApiGetAuthors.as_view(), name='authors'), + path('gifs/', views.ApiGifs.as_view(), name='gifs'), ] diff --git a/src/fachschaftszitat/api/views.py b/src/fachschaftszitat/api/views.py index 31bf163..c0f239a 100644 --- a/src/fachschaftszitat/api/views.py +++ b/src/fachschaftszitat/api/views.py @@ -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,)) @@ -49,6 +49,37 @@ def destroy(self, request, *args, **kwargs): return super().destroy(request, *args, **kwargs) +@permission_classes((IsAuthenticated,)) +class ApiGifs(generics.ListCreateAPIView): + serializer_class = GifSerializer + + def get_queryset(self): + return Gif.objects.filter(creator=self.request.user) + + def create(self, request, *args, **kwargs): + serializer = GifSerializer(data=request.data) + if serializer.is_valid(): + # YOUR CODE HERE + serializer.creator = request.user + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +# def registration_gif(request): +# if request.method == 'POST': +# form = GifForm(request.POST) +# if form.is_valid(): +# gif = form.save(commit=False) +# 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}) + class ApiGetAuthors(generics.ListAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializer diff --git a/src/templates/base.jinja2 b/src/templates/base.jinja2 index e1d0b06..d3c826c 100644 --- a/src/templates/base.jinja2 +++ b/src/templates/base.jinja2 @@ -53,15 +53,54 @@
{% block content %}{% endblock %} -
+ + + + +
© Copyright 2020, Michael Götz (Impressum, Datenschutz) - {# TODO: Fix hidden on small devices#} - Version: {{ version }} - + {# TODO: Fix hidden on small devices#} + Version: {{ version }} +
diff --git a/src/templates/home.jinja2 b/src/templates/home.jinja2 index 3148161..de476e6 100644 --- a/src/templates/home.jinja2 +++ b/src/templates/home.jinja2 @@ -72,42 +72,6 @@ - - - {% endblock %} \ No newline at end of file From f09ff629bea72b462c83e96bf59709f694cf1520 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 10:42:11 +0100 Subject: [PATCH 06/16] fix: form cleaning --- src/static/js/gif_form.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/static/js/gif_form.js b/src/static/js/gif_form.js index cba2faf..952c63c 100644 --- a/src/static/js/gif_form.js +++ b/src/static/js/gif_form.js @@ -49,7 +49,6 @@ $.ajaxSetup({ }); GIFS_FORMULAR.submit(function (event) { - console.log("PREVENT"); event.preventDefault(); var url = GIFS_FORMULAR.attr('action'); $.ajax({ @@ -63,7 +62,7 @@ GIFS_FORMULAR.submit(function (event) { }); function clearGIFFormular() { - GIFS_FORMULAR.empty(); + GIFS_FORMULAR[0].reset(); } function gifSuccessProcess(data) { From 02210ae2a2748b61d20e24b51aa7151fa1e7835b Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 10:59:22 +0100 Subject: [PATCH 07/16] chore: add gif list --- src/static/js/gif_form.js | 31 +++++++++++++++-- src/templates/gif.jinja2 | 72 ++++++--------------------------------- 2 files changed, 39 insertions(+), 64 deletions(-) diff --git a/src/static/js/gif_form.js b/src/static/js/gif_form.js index 952c63c..e62595c 100644 --- a/src/static/js/gif_form.js +++ b/src/static/js/gif_form.js @@ -3,11 +3,11 @@ * http://stackoverflow.com/questions/5100539/django-csrf-check-failing-with-an-ajax-post-request */ // CONFIG -// const GIFS_ENDPOINT = '/gifs'; +const GIFS_ENDPOINT = '/api/gifs'; const GIFS_FORMULAR = $("#gif-form"); -// let source = document.getElementById("entry-template").innerHTML; -// let template = Handlebars.compile(source); +let gifs_source = document.getElementById("gifs-template").innerHTML; +let gifs_template = Handlebars.compile(gifs_source); /* jshint esversion: 6 */ @@ -71,3 +71,28 @@ function gifSuccessProcess(data) { displaySuccessModal(data); clearGIFFormular(); } + +ready(function () { + console.log("Ready"); + updateGifs(); +}); + +function updateGifs() { + $.ajax({ + url: GIFS_ENDPOINT, + type: 'get', + dataType: 'json', + success: resetGifs, + error: displayErrorModal, + }) +} + +function resetGifs(data) { + let gifs = $('#gifs-wrapper'); + let html = ''; + for (const context of data) { + html += gifs_template(context); + } + gifs.empty(); + gifs.append(html) +} diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index 6448b61..bd022a6 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -34,68 +34,18 @@ - {# #} - {#
#} - {#
#} - {#

Zitate

#} - {# #} - {# #} - {# #} - {# {{ mutils.get_list_headline() }}#} - {#
#} - {#
#} - {# {% raw %}#} - {# #} - {# {% endraw %}#} - {#
#} - {#
#} - {#
#} +
+
+ {% raw %} + + {% endraw %} +
+
{% block js_extra_footer %} From e091e3eed760aea1392f2fca2b52740fdf1689a9 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 17:44:41 +0100 Subject: [PATCH 08/16] chore: implement card style --- src/static/home/main.css | 16 +++++++++++++++- src/templates/gif.jinja2 | 36 +++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/static/home/main.css b/src/static/home/main.css index 236afd4..5519b1d 100644 --- a/src/static/home/main.css +++ b/src/static/home/main.css @@ -164,4 +164,18 @@ footer a:active { box-shadow: 0 2px 4px rgba(0, 0, 0, .6); padding: 5px 5px; margin-bottom: 5px; -} \ No newline at end of file +} + +.gif-type{ + position: absolute; + bottom: 0; + right: 15px; +} + +.gif-success-bg { + +} + +.gif-error-bg { + +} diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index bd022a6..8aa3a89 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -11,7 +11,7 @@ {# #}
-
+

Info

Neue gifs können von den folgenden Seiten hinzugefügt werden:

    @@ -34,16 +34,30 @@
- -
-
- {% raw %} - - {% endraw %} +
+
+
+ {% raw %} + + {% endraw %} +
From 9b308856a7b9afa56d331b65f5e99a99d1eddf30 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 17:58:08 +0100 Subject: [PATCH 09/16] chore: add github link to footer --- src/static/home/main.css | 16 ++++++---------- src/templates/base.jinja2 | 13 +++++++------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/static/home/main.css b/src/static/home/main.css index 5519b1d..9750432 100644 --- a/src/static/home/main.css +++ b/src/static/home/main.css @@ -13,7 +13,7 @@ footer { bottom: 0; vertical-align: middle; height: var(--footer-height-y); - line-height: 40px; + line-height: 25px; } footer a:link, @@ -75,7 +75,7 @@ footer a:active { :root { --input-padding-x: .75rem; --input-padding-y: .6rem; - --footer-height-y: 40px + --footer-height-y: 60px } @@ -166,16 +166,12 @@ footer a:active { margin-bottom: 5px; } + +/** **************************************************************************************************************** **/ +/** ******** GIFS ******** **/ +/** **************************************************************************************************************** **/ .gif-type{ position: absolute; bottom: 0; right: 15px; } - -.gif-success-bg { - -} - -.gif-error-bg { - -} diff --git a/src/templates/base.jinja2 b/src/templates/base.jinja2 index d3c826c..d062452 100644 --- a/src/templates/base.jinja2 +++ b/src/templates/base.jinja2 @@ -94,12 +94,13 @@
-
From 88c0ba0d3fa793ea31b8f65231400d0f8c7329ab Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 18:39:03 +0100 Subject: [PATCH 10/16] chore: implement gif deletion --- src/fachschaftszitat/api/serializer.py | 3 +- src/fachschaftszitat/api/urls.py | 3 +- src/fachschaftszitat/api/views.py | 40 +++++++++++++++++--------- src/fachschaftszitat/models.py | 2 +- src/static/js/gif_form.js | 30 +++++++++++++++++-- src/static/js/trash.js | 20 ------------- src/templates/gif.jinja2 | 2 +- 7 files changed, 59 insertions(+), 41 deletions(-) diff --git a/src/fachschaftszitat/api/serializer.py b/src/fachschaftszitat/api/serializer.py index e5cbde2..4c6c7f0 100644 --- a/src/fachschaftszitat/api/serializer.py +++ b/src/fachschaftszitat/api/serializer.py @@ -42,7 +42,8 @@ class GifSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) type = serializers.ChoiceField(choices=Gif.TYPE_CHOICES) video_url = serializers.URLField() - creator = UserSerializer(read_only=True) + is_creator = serializers.BooleanField() + delete_url = serializers.CharField() def create(self, validated_data): return Gif.objects.create(**validated_data) diff --git a/src/fachschaftszitat/api/urls.py b/src/fachschaftszitat/api/urls.py index b91ef30..c4f632d 100644 --- a/src/fachschaftszitat/api/urls.py +++ b/src/fachschaftszitat/api/urls.py @@ -7,5 +7,6 @@ path('quote/', views.ApiGetQuotes.as_view(), name='quotes'), path('quote//', views.ApiRemoveQuote.as_view(), name='delete-quote'), path('author/', views.ApiGetAuthors.as_view(), name='authors'), - path('gifs/', views.ApiGifs.as_view(), name='gifs'), + path('gif/', views.ApiGifs.as_view(), name='gifs'), + path('gif//', views.ApiGif.as_view(), name='delete-gif'), ] diff --git a/src/fachschaftszitat/api/views.py b/src/fachschaftszitat/api/views.py index c0f239a..c880bb2 100644 --- a/src/fachschaftszitat/api/views.py +++ b/src/fachschaftszitat/api/views.py @@ -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: @@ -54,7 +57,15 @@ class ApiGifs(generics.ListCreateAPIView): serializer_class = GifSerializer def get_queryset(self): - return Gif.objects.filter(creator=self.request.user) + 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 def create(self, request, *args, **kwargs): serializer = GifSerializer(data=request.data) @@ -66,19 +77,20 @@ def create(self, request, *args, **kwargs): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) -# def registration_gif(request): -# if request.method == 'POST': -# form = GifForm(request.POST) -# if form.is_valid(): -# gif = form.save(commit=False) -# 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}) +@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() diff --git a/src/fachschaftszitat/models.py b/src/fachschaftszitat/models.py index 53102cb..bc7ed09 100644 --- a/src/fachschaftszitat/models.py +++ b/src/fachschaftszitat/models.py @@ -59,4 +59,4 @@ class Gif(models.Model): creator = models.ForeignKey(User, on_delete=models.PROTECT) def __str__(self): - return f'{self.type} - {self.creator} - {self.video_url}' + return f'{self.id} - {self.type} - {self.creator} - {self.video_url}' diff --git a/src/static/js/gif_form.js b/src/static/js/gif_form.js index e62595c..7211a0c 100644 --- a/src/static/js/gif_form.js +++ b/src/static/js/gif_form.js @@ -3,7 +3,7 @@ * http://stackoverflow.com/questions/5100539/django-csrf-check-failing-with-an-ajax-post-request */ // CONFIG -const GIFS_ENDPOINT = '/api/gifs'; +const GIFS_ENDPOINT = '/api/gif/'; const GIFS_FORMULAR = $("#gif-form"); let gifs_source = document.getElementById("gifs-template").innerHTML; @@ -66,8 +66,7 @@ function clearGIFFormular() { } function gifSuccessProcess(data) { - // TODO update gifs - // updateQuotes(); + updateGifs(); displaySuccessModal(data); clearGIFFormular(); } @@ -96,3 +95,28 @@ function resetGifs(data) { gifs.empty(); gifs.append(html) } + +function confirm_gif_delete() { + return confirm("Möchtest du das GIF wirklich löschen?"); +} + +function resetGifAndDisplaySuccess() { + updateGifs(); + displaySuccessModal(); +} + + +function deleteGif(url) { + const is_confirmed = confirm_gif_delete(); + if (is_confirmed) { + console.log(url); + $.ajax({ + url: url, + type: 'delete', + dataType: 'json', + data: {}, + success: resetGifAndDisplaySuccess, + error: displayErrorModal, + }) + } +} diff --git a/src/static/js/trash.js b/src/static/js/trash.js index 129466e..99ebdc0 100644 --- a/src/static/js/trash.js +++ b/src/static/js/trash.js @@ -1,22 +1,3 @@ -function ready(fn) { - if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") { - fn(); - } else { - document.addEventListener("DOMContentLoaded", fn); - } -} - -ready(function () { - initTrash(); -}); - -function initTrash() { - const trashs = document.getElementsByClassName("trash"); - for (const trash in trashs) { - trash.addE - } -} - function confirm_delete() { return confirm("Möchtest du das Zitat wirklich löschen?"); } @@ -40,5 +21,4 @@ function deleteQuote(url) { error: displayErrorModal, }) } - } \ No newline at end of file diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index 8aa3a89..fd001ea 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -46,7 +46,7 @@
- From a9e5ef2fc9946054c2d37923964201439910e49a Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 18:43:08 +0100 Subject: [PATCH 11/16] chore: move gif_formjs to gifjs --- src/static/js/{gif_form.js => gif.js} | 0 src/templates/gif.jinja2 | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/static/js/{gif_form.js => gif.js} (100%) diff --git a/src/static/js/gif_form.js b/src/static/js/gif.js similarity index 100% rename from src/static/js/gif_form.js rename to src/static/js/gif.js diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index fd001ea..feaaccf 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -62,6 +62,6 @@
{% block js_extra_footer %} - + {% endblock %} {% endblock %} \ No newline at end of file From 21f8e259cfc5da858ebfc1abb1912499da2c7a0e Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 18:45:59 +0100 Subject: [PATCH 12/16] chore: remove unused code --- src/templates/gif.jinja2 | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index feaaccf..fe8bc58 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -2,13 +2,6 @@ {% import 'macros/util_macros.jinja2' as mutils %} {% block content %} - {#
#} - {#
#} - {#
#} - {#

Neues Zitat hinzufügen

#} - {# {{ mutils.get_quote_add_form(statement_formset, user_groups, today_date, authors) }}#} - {#
#} - {#
#}
From 60f360d2d994ab75c3a32ea1e5bce78ef4355fa0 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 19:18:22 +0100 Subject: [PATCH 13/16] chore: implement gif source site and type check --- src/fachschaftszitat/api/views.py | 7 ++++--- src/fachschaftszitat/views.py | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/fachschaftszitat/api/views.py b/src/fachschaftszitat/api/views.py index c880bb2..eb52cdd 100644 --- a/src/fachschaftszitat/api/views.py +++ b/src/fachschaftszitat/api/views.py @@ -71,9 +71,10 @@ def create(self, request, *args, **kwargs): serializer = GifSerializer(data=request.data) if serializer.is_valid(): # YOUR CODE HERE - serializer.creator = request.user - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) + if self.is_video_url_valid(serializer.video_url): + serializer.creator = request.user + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) diff --git a/src/fachschaftszitat/views.py b/src/fachschaftszitat/views.py index 5be4211..d9eebf3 100644 --- a/src/fachschaftszitat/views.py +++ b/src/fachschaftszitat/views.py @@ -83,11 +83,23 @@ def registration_gif(request): form = GifForm(request.POST) if form.is_valid(): gif = form.save(commit=False) - gif.creator = request.user - gif.save() - return JsonResponse({'url': get_random_sucess_url()}, status=201) + 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]) + logger.error(has_known_url_end) + logger.error(has_known_url_start) + + return has_known_url_start and has_known_url_end From ebdd284a06acdfd69647f92d267a803117c60bb8 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 19:23:50 +0100 Subject: [PATCH 14/16] chore: change info text --- src/fachschaftszitat/api/views.py | 12 +----------- src/templates/gif.jinja2 | 5 ++--- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/fachschaftszitat/api/views.py b/src/fachschaftszitat/api/views.py index eb52cdd..df030b2 100644 --- a/src/fachschaftszitat/api/views.py +++ b/src/fachschaftszitat/api/views.py @@ -53,7 +53,7 @@ def destroy(self, request, *args, **kwargs): @permission_classes((IsAuthenticated,)) -class ApiGifs(generics.ListCreateAPIView): +class ApiGifs(generics.ListAPIView): serializer_class = GifSerializer def get_queryset(self): @@ -67,16 +67,6 @@ def get_queryset(self): for gif in gifs] return gifs_wrapper - def create(self, request, *args, **kwargs): - serializer = GifSerializer(data=request.data) - if serializer.is_valid(): - # YOUR CODE HERE - if self.is_video_url_valid(serializer.video_url): - serializer.creator = request.user - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - @permission_classes((IsAuthenticated,)) class ApiGif(generics.DestroyAPIView): diff --git a/src/templates/gif.jinja2 b/src/templates/gif.jinja2 index fe8bc58..658ce26 100644 --- a/src/templates/gif.jinja2 +++ b/src/templates/gif.jinja2 @@ -13,9 +13,8 @@

Bitte beachtet, dass nur mp4 videos akzeptiert werden können. Deshalb ist es bei Tenor nötig auf MP4 umzustellen, bevor man die Video Url kopiert. Dies geht am leichtesten mit einem Rechtsklick und der - anschließenden Auswahl von "Grafikadresse kopieren".
Nutzt bei giphy die Copy link Funktion an - den - mp4 link zu gelangen.

+ anschließenden Auswahl von "Grafikadresse kopieren".
Nutzt bei giphy die Media sharing Funktion auf der rechten Seite, um an + den mp4 link zu gelangen.

From 657ed3836e042ad85c928afa6e58f13bac1bd6e4 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 19:35:06 +0100 Subject: [PATCH 15/16] feat: implement database gifs in success and fail modal, Close #25 --- src/fachschaftszitat/views.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/fachschaftszitat/views.py b/src/fachschaftszitat/views.py index d9eebf3..1c7265b 100644 --- a/src/fachschaftszitat/views.py +++ b/src/fachschaftszitat/views.py @@ -17,13 +17,21 @@ 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. From 9a34a80fd5b270fef516d0b759104c6485f196e6 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 26 Jan 2020 19:38:29 +0100 Subject: [PATCH 16/16] chore: remove unused logs --- src/fachschaftszitat/views.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/fachschaftszitat/views.py b/src/fachschaftszitat/views.py index 1c7265b..79c345f 100644 --- a/src/fachschaftszitat/views.py +++ b/src/fachschaftszitat/views.py @@ -54,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) @@ -107,7 +106,5 @@ def is_video_url_valid(url): 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]) - logger.error(has_known_url_end) - logger.error(has_known_url_start) return has_known_url_start and has_known_url_end