Compare commits
No commits in common. "7277fc7b5cff3f77e007a18b2502f3490d2607d3" and "cc93abc75293eb21ff1c754d5a88a02791d1fa43" have entirely different histories.
7277fc7b5c
...
cc93abc752
|
@ -119,5 +119,3 @@ USE_TZ = True
|
||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
LOGIN_URL = '/accounts/login/'
|
|
||||||
|
|
|
@ -18,6 +18,5 @@ from django.urls import path, include
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('writing/', include('writingtogether.urls')),
|
path('writing/', include('writingtogether.urls')),
|
||||||
path('accounts/', include('django.contrib.auth.urls')),
|
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import CASCADE
|
from django.db.models import CASCADE
|
||||||
|
@ -31,14 +29,6 @@ class StoryRound(models.Model):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def advance_to_next_turn_and_get_status_and_round_number(self) -> Tuple[str, int]:
|
|
||||||
if self.current_turn+1 == self.number_of_rounds:
|
|
||||||
return 'finished', self.current_turn
|
|
||||||
self.current_turn += 1
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
return 'ongoing', self.current_turn
|
|
||||||
|
|
||||||
|
|
||||||
#class Participant(models.Model):
|
#class Participant(models.Model):
|
||||||
# user = models.ForeignKey(User, on_delete=CASCADE)
|
# user = models.ForeignKey(User, on_delete=CASCADE)
|
||||||
|
@ -70,9 +60,9 @@ class StoryPart(models.Model):
|
||||||
user = models.ForeignKey(User, on_delete=CASCADE)
|
user = models.ForeignKey(User, on_delete=CASCADE)
|
||||||
previous_part = models.ForeignKey('StoryPart', on_delete=CASCADE, null=True, blank=True)
|
previous_part = models.ForeignKey('StoryPart', on_delete=CASCADE, null=True, blank=True)
|
||||||
text = models.TextField(null=True, blank=True)
|
text = models.TextField(null=True, blank=True)
|
||||||
part_of = models.ForeignKey('Story', on_delete=CASCADE, related_name='parts')
|
part_of = models.ForeignKey('Story', on_delete=CASCADE)
|
||||||
turn_number = models.IntegerField()
|
turn_number = models.IntegerField()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def finished(self):
|
def finished(self):
|
||||||
return bool(self.text)
|
return self.text
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{% if form.errors %}
|
|
||||||
<p>Your username and password didn't match. Please try again.</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if next %}
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>Your account doesn't have access to this page. To proceed,
|
|
||||||
please login with an account that has access.</p>
|
|
||||||
{% else %}
|
|
||||||
<p>Please login to see this page.</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<form method="post" action="{% url 'login' %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>{{ form.username.label_tag }}</td>
|
|
||||||
<td>{{ form.username }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>{{ form.password.label_tag }}</td>
|
|
||||||
<td>{{ form.password }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<input type="submit" value="login">
|
|
||||||
<input type="hidden" name="next" value="{{ next }}">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{# Assumes you setup the password_reset view in your URLconf #}
|
|
||||||
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title></title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Fertig!</h1>
|
|
||||||
|
|
||||||
{% for story in stories %}
|
|
||||||
{% for story_part in story.parts.all %}
|
|
||||||
|
|
||||||
<div>{{ story_part.text }} <i>({{ story_part.user }})</i></div>
|
|
||||||
{% endfor %}
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -5,12 +5,8 @@
|
||||||
<title>Title</title>
|
<title>Title</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Runde {{ current_round }} / {{ total_rounds }}</h1>
|
|
||||||
|
|
||||||
{% if previous_part %}
|
<form action="{% url 'writing:create_story_part' %}" method="post">
|
||||||
<div>Letzter Satz: {{ previous_part.text }}</div>
|
|
||||||
{% endif %}
|
|
||||||
<form action="{% url 'writing:update_story_part' story_round_pk=story_round_pk story_pk=story_pk pk=pk %}" method="post">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.as_p }}
|
{{ form.as_p }}
|
||||||
<input type="submit" value="Submit">
|
<input type="submit" value="Submit">
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title></title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>Die nächste Runde ist noch nicht bereit.</div>
|
|
||||||
<div>Klick hier um zu prüfen, ob die anderen fertig sind:
|
|
||||||
<a href="{% url 'writing:redirect_story_part' story_round_pk=object.pk %}">nächste Runde</a>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -9,9 +9,8 @@ User = get_user_model()
|
||||||
|
|
||||||
class TestViews(TestCase):
|
class TestViews(TestCase):
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self.user1 = User.objects.create_user(username='player1', password='12345')
|
self.user1 = User.objects.create(username='player1')
|
||||||
self.user2 = User.objects.create_user(username='player2')
|
self.user2 = User.objects.create(username='player2')
|
||||||
self.client.login(username='player1', password='12345')
|
|
||||||
|
|
||||||
def test_create_story_round_two_rounds(self):
|
def test_create_story_round_two_rounds(self):
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@ urlpatterns = [
|
||||||
path('', views.IndexView.as_view(), name='index'),
|
path('', views.IndexView.as_view(), name='index'),
|
||||||
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
|
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
|
||||||
path('create/', views.StoryRoundCreate.as_view(), name='create_story_round'),
|
path('create/', views.StoryRoundCreate.as_view(), name='create_story_round'),
|
||||||
path('open/<int:story_round_pk>/<int:story_pk>/<int:pk>/', views.StoryPartUpdate.as_view(), name='update_story_part'),
|
path('open/<int:story_round_pk>/<int:story_pk>/<int:story_part_pk>/', views.StoryPartUpdate.as_view(), name='update_story_part'),
|
||||||
path('open/<int:pk>/waiting/', views.WaitForOthersView.as_view(), name='wait_for_others'),
|
|
||||||
path('open/<int:story_round_pk>/', views.RedirectToNextOpenPart.as_view(), name='redirect_story_part'),
|
path('open/<int:story_round_pk>/', views.RedirectToNextOpenPart.as_view(), name='redirect_story_part'),
|
||||||
path('finished/<int:pk>/', views.RoundFinishedView.as_view(), name ='finished'),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
from django.urls import reverse_lazy, reverse
|
from django.urls import reverse_lazy, reverse
|
||||||
from django.views.generic import CreateView, UpdateView, RedirectView, DetailView, ListView
|
from django.views import generic
|
||||||
|
from django.views.generic import CreateView, UpdateView, RedirectView
|
||||||
|
|
||||||
from writingtogether.models import Story, StoryPart, StoryRound
|
from writingtogether.models import Story, StoryPart, StoryRound
|
||||||
|
|
||||||
|
|
||||||
class IndexView(LoginRequiredMixin, ListView):
|
class IndexView(generic.ListView):
|
||||||
template_name = 'writingtogether/index.html'
|
template_name = 'writingtogether/index.html'
|
||||||
context_object_name = 'open_story_round_list'
|
context_object_name = 'open_story_round_list'
|
||||||
|
|
||||||
|
@ -18,12 +19,12 @@ class IndexView(LoginRequiredMixin, ListView):
|
||||||
return StoryRound.objects.order_by('-created')[:5]
|
return StoryRound.objects.order_by('-created')[:5]
|
||||||
|
|
||||||
|
|
||||||
class StoryRoundDetailView(LoginRequiredMixin, DetailView):
|
class DetailView(generic.DetailView):
|
||||||
model = StoryRound
|
model = StoryRound
|
||||||
template_name = 'writingtogether/detail.html'
|
template_name = 'writingtogether/detail.html'
|
||||||
|
|
||||||
|
|
||||||
class StoryRoundCreate(LoginRequiredMixin, CreateView):
|
class StoryRoundCreate(CreateView):
|
||||||
model = StoryRound
|
model = StoryRound
|
||||||
fields = ['name', 'participants', 'number_of_rounds']
|
fields = ['name', 'participants', 'number_of_rounds']
|
||||||
success_url = reverse_lazy('writing:index')
|
success_url = reverse_lazy('writing:index')
|
||||||
|
@ -52,27 +53,15 @@ class StoryRoundCreate(LoginRequiredMixin, CreateView):
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
|
|
||||||
class StoryUpdate(LoginRequiredMixin, UpdateView):
|
class StoryUpdate(UpdateView):
|
||||||
model = Story
|
model = Story
|
||||||
fields = ['name']
|
fields = ['name']
|
||||||
|
|
||||||
|
|
||||||
class StoryPartUpdate(LoginRequiredMixin, UpdateView):
|
class StoryPartUpdate(UpdateView):
|
||||||
model = StoryPart
|
model = StoryPart
|
||||||
fields = ['text']
|
fields = ['text']
|
||||||
template_name = 'writingtogether/story_part.html'
|
template_name = 'writingtogether/story_part.html'
|
||||||
success_url = reverse_lazy('writing:index')
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(StoryPartUpdate, self).get_context_data(**kwargs)
|
|
||||||
context.update({
|
|
||||||
'current_round': self.object.turn_number + 1,
|
|
||||||
'total_rounds': self.object.part_of.part_of_round.number_of_rounds,
|
|
||||||
'previous_part': self.object.previous_part,
|
|
||||||
})
|
|
||||||
context.update(self.kwargs)
|
|
||||||
return context
|
|
||||||
|
|
||||||
|
|
||||||
#def form_valid(self, form):
|
#def form_valid(self, form):
|
||||||
# form.instance.created_by = self.request.user
|
# form.instance.created_by = self.request.user
|
||||||
|
@ -81,7 +70,7 @@ class StoryPartUpdate(LoginRequiredMixin, UpdateView):
|
||||||
# return super().form_valid(form)
|
# return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class RedirectToNextOpenPart(LoginRequiredMixin, RedirectView):
|
class RedirectToNextOpenPart(RedirectView):
|
||||||
permanent = False
|
permanent = False
|
||||||
query_string = True
|
query_string = True
|
||||||
pattern_name = 'writing:update_story_part'
|
pattern_name = 'writing:update_story_part'
|
||||||
|
@ -89,34 +78,8 @@ class RedirectToNextOpenPart(LoginRequiredMixin, RedirectView):
|
||||||
def get_redirect_url(self, *args, **kwargs):
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
story_round = get_object_or_404(StoryRound, pk=kwargs['story_round_pk'])
|
story_round = get_object_or_404(StoryRound, pk=kwargs['story_round_pk'])
|
||||||
|
|
||||||
if story_round.next_round_ready():
|
|
||||||
status, turn_number = story_round.advance_to_next_turn_and_get_status_and_round_number()
|
|
||||||
if status == 'finished':
|
|
||||||
self.pattern_name = 'writing:finished'
|
|
||||||
kwargs['pk'] = kwargs.pop('story_round_pk')
|
|
||||||
return super().get_redirect_url(*args, **kwargs)
|
|
||||||
|
|
||||||
story_part = story_round.get_next_story_part(user=self.request.user)
|
story_part = story_round.get_next_story_part(user=self.request.user)
|
||||||
|
|
||||||
if story_part.finished:
|
|
||||||
self.pattern_name = 'writing:wait_for_others'
|
|
||||||
kwargs['pk'] = kwargs.pop('story_round_pk')
|
|
||||||
else:
|
|
||||||
kwargs['story_pk'] = story_part.part_of.pk
|
kwargs['story_pk'] = story_part.part_of.pk
|
||||||
kwargs['pk'] = story_part.pk
|
kwargs['story_part_pk'] = story_part.pk
|
||||||
|
|
||||||
return super().get_redirect_url(*args, **kwargs)
|
return super().get_redirect_url(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class WaitForOthersView(LoginRequiredMixin, DetailView):
|
|
||||||
model = StoryRound
|
|
||||||
template_name = 'writingtogether/wait_for_others.html'
|
|
||||||
|
|
||||||
|
|
||||||
class RoundFinishedView(LoginRequiredMixin, ListView):
|
|
||||||
model = Story
|
|
||||||
context_object_name = 'stories'
|
|
||||||
template_name = 'writingtogether/finished.html'
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return Story.objects.filter(part_of_round_id=self.kwargs['pk']).prefetch_related('parts')
|
|
Loading…
Reference in New Issue