diff --git a/news/forms.py b/news/forms.py index 843a31a652217ae7a9d7d87e61a1f862f681a0ff..3e63731157969d2a2cbb02edefb8a02d8b5b40d0 100644 --- a/news/forms.py +++ b/news/forms.py @@ -29,3 +29,17 @@ class NewsLetterNewsItemsTableForm(forms.ModelForm): class Meta: model = NewsLetterNewsItemsTable fields = ['newsitem'] + + +class NewsLetterNewsItemsTableFormSet(forms.BaseModelFormSet): + def save(self, *args, **kwargs): + objects = super().save(*args, **kwargs) + for form in self.ordered_forms: + form.instance.order = form.cleaned_data['ORDER'] + form.instance.save() + return objects + + +NewsLetterNewsItemsOrderingFormSet = forms.modelformset_factory( + NewsLetterNewsItemsTable, fields=(), can_order=True, extra=0, + formset=NewsLetterNewsItemsTableFormSet) diff --git a/news/templates/news/_newsletter_contents.html b/news/templates/news/_newsletter_contents.html index 452b4e972a8d9dcbe532ec8223d09d81b6103242..dfdaf6249d372fccfd342076c23f9c05f1ea4754 100644 --- a/news/templates/news/_newsletter_contents.html +++ b/news/templates/news/_newsletter_contents.html @@ -1,6 +1,6 @@ <div class="row"> <div class="col-12"> - <div class="card card-grey card-news"> + <div class="card card-grey card-news p-3"> <h1>SciPost Newsletter {{ nl.date|date:'Y-m-d' }}</h1> <p>{{ nl.intro|safe }}</p> </div> @@ -9,7 +9,7 @@ {% include 'news/news_card_content.html' with news=nt.newsitem %} </div> {% endfor %} - <div class="card card-grey card-news"> + <div class="card card-grey card-news p-3"> <p>{{ nl.closing|safe }}</p> </div> </div> diff --git a/news/templates/news/news_card_content.html b/news/templates/news/news_card_content.html index 99c6e78098a599e7c31fc4d6b47ae234dfb550e6..312340de922aaabdb87f237a9e0675127862d926 100644 --- a/news/templates/news/news_card_content.html +++ b/news/templates/news/news_card_content.html @@ -2,10 +2,10 @@ {% if news.image %} <div class="row"> - <div class="col-3"> + <div class="col-2"> <img class="d-flex mr-3 {{ news.image.css_class }}" src="{{ news.image.url }}" alt="image"/> </div> - <div class="col-9"> + <div class="col-10"> {% endif %} <div> <h2 class="card-title">{{news.headline}}</h2> diff --git a/news/templates/news/news_manage.html b/news/templates/news/news_manage.html index 282fd278e857a644b5356517a008142624d67b86..fa5297d71c33f579ab013b5c9192432a6d43636b 100644 --- a/news/templates/news/news_manage.html +++ b/news/templates/news/news_manage.html @@ -5,45 +5,74 @@ {% block pagetitle %}: News Management{% endblock pagetitle %} {% block content %} +<div class="row"> + <div class="col-12"> + <h1>News Management</h1> + </div> +</div> + + +<hr/> <div class="row"> <div class="col-12"> <h1>NewsLetters</h1> <a href="{% url 'news:newsletter_create' %}">Add a NewsLetter</a> - <br/> - <ul> - {% for nl in newsletters %} - <li> - <div><a href="{{ nl.get_absolute_url }}">{{ nl }}</a> <strong>Actions:</strong> <a href="{% url 'news:newsletter_update' pk=nl.id %}">Update</a> <a href="{% url 'news:newsletter_delete' pk=nl.id %}">Delete</a> - <h3>Add a News Item to this Newsletter:</h3> - <form class="d-block mt-2 mb-3" action="{% url 'news:add_newsitem_to_newsletter' nlpk=nl.id %}" method="post"> - {% csrf_token %} - {{ add_ni_to_nl_form|bootstrap }} - <input type="submit" name="submit" value="Add" class="btn btn-outline-secondary"> - </form> + <br/><br/> + {% for nl in newsletters %} + <div class="card"> + <div class="card-header"> + <a href="{{ nl.get_absolute_url }}">{{ nl }}</a> + (status: {% if nl.published %}published{% else %}unpublished{% endif %}) + </div> + <div class="card-body"> + <div class="row"> + <div class="col-6"> + <h3>NewsItems included in this Newsletter:</h3> + <ul> + {% for nt in nl.newsletternewsitemstable_set.all|dictsort:'order' %} + <li>{{ nt.newsitem }}</li> + {% empty %} + <li>No associated NewsItems found</li> + {% endfor %} + </ul> + </div> + <div class="col-6"> + <h3>Actions:</h3> + <ul> + <li><a href="{% url 'news:newsletter_update' pk=nl.id %}">Update</a></li> + <li><a href="{% url 'news:newsletter_update_ordering' pk=nl.id %}">Update items ordering</a></li> + <li><a href="{% url 'news:newsletter_delete' pk=nl.id %}">Delete</a></li> + <li> + Add a News Item to this Newsletter: + <form class="d-block mt-2 mb-3" action="{% url 'news:add_newsitem_to_newsletter' nlpk=nl.id %}" method="post"> + {% csrf_token %} + {{ add_ni_to_nl_form|bootstrap }} + <input type="submit" name="submit" value="Add" class="btn btn-outline-secondary"> + </form> + </li> + </ul> + </div> </div> - <ul> - {% for nt in nl.newsletternewsitemstable_set.all %} - <li>{{ nt.newsitem }}</li> - {% empty %} - <li>No associated NewsItems found</li> - {% endfor %} - </ul> - </li> + </div> {% endfor %} - </ul> + </div> </div> -</div> +<hr/> <div class="row"> <div class="col-12"> <h1>NewsItems</h1> <a href="{% url 'news:newsitem_create' %}">Add a NewsItem</a> - <br/> - <ul> + <br/><br/> + <table class="table"> {% for ni in newsitems %} - <li>{{ ni }} <a href="{% url 'news:newsitem_update' pk=ni.id %}">Update</a> <a href="{% url 'news:newsitem_delete' pk=ni.id %}">Delete</a></li> + <tr> + <td>{{ ni }}</td> + <td><a href="{% url 'news:newsitem_update' pk=ni.id %}">Update</a></td> + <td><a href="{% url 'news:newsitem_delete' pk=ni.id %}">Delete</a></td> + </tr> {% endfor %} - </ul> + </table> </div> </div> {% endblock content %} diff --git a/news/templates/news/newsitem_list.html b/news/templates/news/newsitem_list.html index af456a7bad6786002590219ce970ce214116446b..d4d56e92dc6a08d5fb03e5b39ce27c380f90d0f4 100644 --- a/news/templates/news/newsitem_list.html +++ b/news/templates/news/newsitem_list.html @@ -11,7 +11,7 @@ <div class="col-12"> <h1 class="highlight">SciPost News</h1> {% if perms.scipost.can_manage_news %} - Go to the <a href="{% url 'news:manage' %}">News management page</a> + <p>Go to the <a href="{% url 'news:manage' %}">News management page</a></p> {% endif %} </div> </div> diff --git a/news/templates/news/newsletter_detail.html b/news/templates/news/newsletter_detail.html index be923e3edb62e9369b89fd51bbaa420378ed8355..3e68090e6b697b6a8388e47956360e1b0f119b4b 100644 --- a/news/templates/news/newsletter_detail.html +++ b/news/templates/news/newsletter_detail.html @@ -8,6 +8,9 @@ <div class="row"> <div class="col-12"> + {% if perms.scipost.can_manage_news %} + <p>Go to the <a href="{% url 'news:manage' %}">News management page</a></p> + {% endif %} {% include 'news/_newsletter_contents.html' with nl=nl %} </div> </div> diff --git a/news/templates/news/newsletter_update_ordering.html b/news/templates/news/newsletter_update_ordering.html new file mode 100644 index 0000000000000000000000000000000000000000..22c59107286bdd04d177dbff65328e54386dbbff --- /dev/null +++ b/news/templates/news/newsletter_update_ordering.html @@ -0,0 +1,46 @@ +{% extends 'scipost/base.html' %} + +{% load bootstrap %} + +{% block pagetitle %}: NewsLetters{% endblock pagetitle %} + +{% block breadcrumb_items %} +{{ block.super }} +<a href="{% url 'news:news' %}" class="breadcrumb-item">News</a> +<a href="{% url 'news:manage' %}" class="breadcrumb-item">Manage</a> +<span class="breadcrumb-item">Update NewsLetter Ordering</span> +{% endblock breadcrumb_items %} + + +{% block content %} + +<div class="row"> + <div class="col-12"> + <h1>Newsletter to update:</h1> + {{ object }} + </div> +</div> + + <hr/> + +<div class="row"> + <div class="col-12"> + <h1>Update the ordering of News Items within this Newsletter:</h1> + <form method="post" enctype="multipart/form-data"> + {% csrf_token %} + {{ ni_formset.management_form }} + <ul class="fa-ul sortable-list d-inline-block"> + {% for ni_form in ni_formset %} + <li> + <i class="fa fa-sort"></i> + {{ ni_form.instance.newsitem }} + <div class="d-none">{{ ni_form }}</div> + </li> + {% endfor %} + </ul> + <br/> + <input type="submit" class="btn btn-primary" value="Save ordering"> + </form> + </div> +</div> +{% endblock content %} diff --git a/news/urls.py b/news/urls.py index 3c28fe51dc7c993f3f3f300f036f77326fe67451..01e0dc5cabc1860d156444d517e243f07e79d0ee 100644 --- a/news/urls.py +++ b/news/urls.py @@ -19,6 +19,10 @@ urlpatterns = [ url(r'^newsletter/(?P<pk>[0-9]+)/update/$', views.NewsLetterUpdateView.as_view(), name='newsletter_update'), + url(r'^newsletter/(?P<pk>[0-9]+)/update_ordering/$', + #views.NewsLetterNewsItemsOrderingUpdateView.as_view(), + views.newsletter_update_ordering, + name='newsletter_update_ordering'), url(r'^newsletter/(?P<pk>[0-9]+)/delete/$', views.NewsLetterDeleteView.as_view(), name='newsletter_delete'), diff --git a/news/views.py b/news/views.py index 377fd677542ed71f800639cfe1ad009ef9d882f0..8de18488590dac431b719155e20c082734df959a 100644 --- a/news/views.py +++ b/news/views.py @@ -4,14 +4,17 @@ __license__ = "AGPL v3" from django.contrib import messages from django.core.urlresolvers import reverse_lazy -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, render, redirect from django.views.generic.base import TemplateView from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.detail import DetailView from django.views.generic.list import ListView -from .models import NewsLetter, NewsItem -from .forms import NewsLetterForm, NewsItemForm, NewsLetterNewsItemsTableForm +from guardian.decorators import permission_required + +from .models import NewsLetter, NewsItem, NewsLetterNewsItemsTable +from .forms import NewsLetterForm, NewsItemForm, NewsLetterNewsItemsTableForm,\ + NewsLetterNewsItemsOrderingFormSet from scipost.mixins import PermissionsMixin @@ -67,6 +70,51 @@ class NewsLetterUpdateView(PermissionsMixin, UpdateView): success_url = reverse_lazy('news:news') +@permission_required('scipost.can_manage_news', raise_exception=True) +def newsletter_update_ordering(request, pk): + newsletter = get_object_or_404(NewsLetter, pk=pk) + ni_formset = NewsLetterNewsItemsOrderingFormSet( + request.POST or None, queryset=newsletter.newsletternewsitemstable_set.order_by('order')) + if ni_formset.is_valid(): + ni_formset.save() + messages.success(request, 'Newsletter items ordering updated') + return redirect(newsletter.get_absolute_url()) + context = { + 'ni_formset': ni_formset, + } + return render(request, 'news/newsletter_update_ordering.html', context) + + +class NewsLetterNewsItemsOrderingUpdateView(PermissionsMixin, UpdateView): + """ + Update the ordering of News Items within a Newsletter. + """ + permission_required = 'scipost.can_manage_news' + model = NewsLetterNewsItemsTable + fields = ['order'] + template_name = 'news/newsletter_update_ordering.html' + success_url = reverse_lazy('news:news') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + newsletter = get_object_or_404(NewsLetter, id=self.kwargs['pk']) + context['ni_formset'] = NewsLetterNewsItemsOrderingFormSet( + self.request.POST or None, + queryset=newsletter.newsletternewsitemstable_set.order_by('order')) + return context + + # def form_valid(self, form): + # context = self.get_context_data() + # ni_formset = context['ni_formset'] + # if ni_formset.is_valid(): + # # self.object = form.save() + # # ni_formset.instance = self.object + # ni_formset.save() + # return redirect(self.success_url) + # else: + # return self.render_to_response(self.get_context_data(form=form)) + + class NewsLetterDeleteView(PermissionsMixin, DeleteView): """ Delete a NewsLetter.