diff --git a/forums/forms.py b/forums/forms.py index ce91c1096fc169289f02684f29d570feeaff8de8..721c36c9f41a1fcaa83f27bc99cc9e447151c045 100644 --- a/forums/forms.py +++ b/forums/forms.py @@ -58,3 +58,16 @@ class PostForm(forms.ModelForm): self.fields['needs_vetting'].widget = forms.HiddenInput() self.fields['parent_content_type'].widget = forms.HiddenInput() self.fields['parent_object_id'].widget = forms.HiddenInput() + + +class PostFormHidden(PostForm): + class Meta: + model = Post + fields = ['posted_by', 'posted_on', 'needs_vetting', + 'parent_content_type', 'parent_object_id', + 'subject', 'text'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['subject'].widget = forms.HiddenInput() + self.fields['text'].widget = forms.HiddenInput() diff --git a/forums/templates/forums/forum_list.html b/forums/templates/forums/forum_list.html index aa5e8373ab7b49f2e9cd6e97271397605c4e46ca..d5f0b6948ace9de47bcd2f8352f75375faea8d64 100644 --- a/forums/templates/forums/forum_list.html +++ b/forums/templates/forums/forum_list.html @@ -28,7 +28,7 @@ <div class="card"> <div class="card-header d-flex justify-content-between"> <a href="{{ forum.get_absolute_url }}">{{ forum }}</a> - <span class="badge badge-primary badge-pill">{{ forum.nr_posts }} posts</span> + <span class="badge badge-primary badge-pill">{{ forum.nr_posts }} post{{ forum.nr_posts|pluralize }}</span> </div> <div class="card-body"> Forum description diff --git a/forums/templates/forums/post_card.html b/forums/templates/forums/post_card.html index 07339376bed33ffd6318c21b52a12f167439378b..e9eee97ac4cdb8928a3d54cc1cdcd680bec7420c 100644 --- a/forums/templates/forums/post_card.html +++ b/forums/templates/forums/post_card.html @@ -15,11 +15,13 @@ {{ post.text|restructuredtext }} </div> <div class="card-footer"> + {% if post.followup_posts.all|length > 0 %} + <span class="badge badge-primary badge-pill">{% with nr_followups=post.nr_followups %}{{ nr_followups }} repl{{ nr_followups|pluralize:"y,ies" }}{% endwith %}</span> + {% endif %} <a href="{% url 'forums:post_create' slug=forum.slug parent_model='post' parent_id=post.id %}">Reply to this post</a> </div> {% if post.followup_posts.all|length > 0 %} <div class="followupPosts"> - <h3><span class="badge badge-primary badge-pill">{% with nr_followups=post.nr_followups %}{{ nr_followups }} repl{{ nr_followups|pluralize:"y,ies" }}{% endwith %}</span></h3> {% for followup in post.followup_posts.all %} {% include 'forums/post_card.html' with post=followup %} {% endfor %} diff --git a/forums/templates/forums/post_confirm_create.html b/forums/templates/forums/post_confirm_create.html new file mode 100644 index 0000000000000000000000000000000000000000..c0f4b229cfa437a802f473b5f6331c42df4dafb3 --- /dev/null +++ b/forums/templates/forums/post_confirm_create.html @@ -0,0 +1,58 @@ +{% extends 'forums/base.html' %} + +{% load bootstrap %} +{% load restructuredtext %} + + +{% block breadcrumb_items %} +{{ block.super }} +<span class="breadcrumb-item">Confirm Post creation</span> +{% endblock %} + +{% block pagetitle %}: Post: confirm creation{% endblock pagetitle %} + +{% block content %} + +<div class="row"> + <div class="col-12"> + <h3 class="highlight">Preview</h3> + + <div class="card"> + <div class="card-header"> + {{ form.initial.subject }} + </div> + <div class="card-body"> + {% if form.initial.text %} + {{ form.initial.text|restructuredtext }} + {% else %} + <span class="text-danger">No text given</span> + {% endif %} + </div> + </div> + + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} + <div class="alert alert-danger"> + <strong>{{ field.name }} - {{ error|escape }}</strong> + </div> + {% endfor %} + {% endfor %} + {% for error in form.non_field_errors %} + <div class="alert alert-danger"> + <strong>{{ error|escape }}</strong> + </div> + {% endfor %} + {% endif %} + + <form action="" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input type="submit" value="Confirm Post creation" class="btn btn-primary"> + <span class="text-danger">Not happy? Hit your browser's back button and redraft your Post</span> + </form> + + </div> +</div> + +{% endblock content %} diff --git a/forums/templates/forums/post_form.html b/forums/templates/forums/post_form.html index 8b6b1c3a28f4a2a6286c3732b0a15b1e0da7ae8c..867b3e610d6ce4bc9dce735f54e7bd3a657de793 100644 --- a/forums/templates/forums/post_form.html +++ b/forums/templates/forums/post_form.html @@ -1,6 +1,8 @@ {% extends 'forums/base.html' %} {% load bootstrap %} +{% load restructuredtext %} + {% block breadcrumb_items %} {{ block.super }} @@ -13,10 +15,12 @@ <div class="row"> <div class="col-12"> + <h3 class="highlight">Compose a new Post</h3> <form action="" method="post"> {% csrf_token %} {{ form|bootstrap }} - <input type="submit" value="Submit" class="btn btn-primary"> + <input type="submit" value="Run preview" class="btn btn-primary"> + </form> </div> </div> diff --git a/forums/urls.py b/forums/urls.py index 62cbc9352dc12d11286ea72696aa7bc8469367ec..f2577a96f66a67b639c5015c2c4245bf98ec48b7 100644 --- a/forums/urls.py +++ b/forums/urls.py @@ -47,4 +47,9 @@ urlpatterns = [ views.PostCreateView.as_view(), name='post_create' ), + url( + r'(?P<slug>[\w-]+)/post/(?P<parent_model>[a-z]+)/(?P<parent_id>[0-9]+)/add/confirm/$', + views.PostConfirmCreateView.as_view(), + name='post_confirm_create' + ), ] diff --git a/forums/views.py b/forums/views.py index 25fee032b497e2984748130712ea093f4dcaf28b..bc5157ba95eb9ab12a2f33a36f05a46632052431 100644 --- a/forums/views.py +++ b/forums/views.py @@ -4,12 +4,12 @@ __license__ = "AGPL v3" from django.contrib import messages from django.contrib.auth.models import Group -from django.contrib.auth.mixins import UserPassesTestMixin +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.contrib.contenttypes.models import ContentType from django.core.exceptions import PermissionDenied -from django.core.urlresolvers import reverse_lazy from django.http import Http404 from django.shortcuts import get_object_or_404, redirect +from django.urls import reverse, reverse_lazy from django.utils import timezone from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView, UpdateView, DeleteView @@ -20,7 +20,8 @@ from guardian.shortcuts import (assign_perm, remove_perm, get_objects_for_user, get_perms, get_users_with_perms, get_groups_with_perms) from .models import Forum, Post -from .forms import ForumForm, ForumGroupPermissionsForm, ForumOrganizationPermissionsForm, PostForm +from .forms import (ForumForm, ForumGroupPermissionsForm, ForumOrganizationPermissionsForm, + PostForm, PostFormHidden) from scipost.mixins import PermissionsMixin @@ -121,7 +122,7 @@ class ForumPermissionsView(PermissionRequiredMixin, UpdateView): return super().form_valid(form) -class ForumListView(ListView): +class ForumListView(LoginRequiredMixin, ListView): model = Forum template_name = 'forum_list.html' @@ -165,5 +166,48 @@ class PostCreateView(UserPassesTestMixin, CreateView): }) return initial - def get_success_url(self): - return self.object.get_absolute_url() + def form_valid(self, form): + """ + Save the form data to session variables only, redirect to confirmation view. + """ + self.request.session['post_subject'] = form.cleaned_data['subject'] + self.request.session['post_text'] = form.cleaned_data['text'] + return redirect(reverse('forums:post_confirm_create', + kwargs={'slug': self.kwargs.get('slug'), + 'parent_model': self.kwargs.get('parent_model'), + 'parent_id': self.kwargs.get('parent_id')})) + + +class PostConfirmCreateView(UserPassesTestMixin, CreateView): + form_class = PostFormHidden + template_name = 'forums/post_confirm_create.html' + + def test_func(self): + if self.request.user.has_perm('forums.add_forum'): + return True + forum = get_object_or_404(Forum, slug=self.kwargs.get('slug')) + if self.request.user.has_perm('can_post_to_forum', forum): + return True + else: + raise PermissionDenied + + def get_initial(self, *args, **kwargs): + initial = super().get_initial(*args, **kwargs) + parent_model = self.kwargs.get('parent_model') + parent_object_id = self.kwargs.get('parent_id') + if parent_model == 'forum': + parent_content_type = ContentType.objects.get(app_label='forums', model='forum') + elif parent_model == 'post': + parent_content_type = ContentType.objects.get(app_label='forums', model='post') + parent = parent_content_type.get_object_for_this_type(pk=parent_object_id) + else: + raise Http404 + initial.update({ + 'posted_by': self.request.user, + 'posted_on': timezone.now(), + 'parent_content_type': parent_content_type, + 'parent_object_id': parent_object_id, + 'subject': self.request.session['post_subject'], + 'text': self.request.session['post_text'], + }) + return initial