diff --git a/templates/featured/index.html b/templates/featured/index.html
index 94902e083c..7c3cc59472 100644
--- a/templates/featured/index.html
+++ b/templates/featured/index.html
@@ -1,6 +1,7 @@
{% extends "featured/base.html" %}
{% load i18n %}
{% load remove_url_protocole %}
+{% load date %}
{% block title %}
{% trans "Liste des unes" %}
@@ -45,6 +46,7 @@
class="topic-image"
>
{{ featured_resource.title }}
+ {% trans 'Publiée' %} {{ featured_resource.pubdate|format_date:True|lower }}
diff --git a/zds/featured/forms.py b/zds/featured/forms.py
index 1ed95bbbf3..d11f5ab672 100644
--- a/zds/featured/forms.py
+++ b/zds/featured/forms.py
@@ -13,7 +13,7 @@ class FeaturedResourceForm(forms.ModelForm):
class Meta:
model = FeaturedResource
- fields = ['title', 'type', 'authors', 'image_url', 'url', 'pubdate']
+ fields = ['title', 'type', 'authors', 'image_url', 'url']
widgets = {
'title': forms.TextInput(
@@ -44,12 +44,6 @@ class Meta:
attrs={
'placeholder': _(u'Lien vers la ressource.')
}
- ),
-
- 'pubdate': forms.DateTimeInput(
- attrs={
- 'placeholder': _(u'Exemple : 2016-12-25 00:00:00')
- }
)
}
@@ -59,25 +53,48 @@ class Meta:
required=False
)
+ pubdate = forms.DateTimeField(
+ label=_(u'Date de publication (exemple: 25/12/2015 15:00 ou 2015-12-25T15:00)'),
+ input_formats=[
+ '%d/%m/%Y %H:%M:%S', '%Y-%m-%d %H:%M:%S', # full format with second
+ '%Y-%m-%dT%H:%M', # datetime field format
+ '%Y-%m-%d %H:%M', '%d/%m/%Y %H:%M', # without second
+ '%Y-%m-%d', '%d/%m/%Y' # day only
+ ],
+ widget=forms.DateTimeInput(
+ attrs={'placeholder': _(u'Exemple : 25/12/2016 10:00'), 'type': 'datetime-local'},
+ format='%Y-%m-%dT%H:%M' # datetime field format
+ )
+ )
+
def __init__(self, *args, **kwargs):
+ hide_major_update_field = kwargs.pop('hide_major_update_field', False)
+
super(FeaturedResourceForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_class = 'content-wrapper'
self.helper.form_method = 'post'
self.helper.form_action = reverse('featured-resource-create')
- self.helper.layout = Layout(
+ fields = [
Field('title'),
Field('type'),
Field('authors'),
Field('image_url'),
- Field('url'),
- Field('major_update'),
+ Field('url')
+ ]
+
+ if not hide_major_update_field:
+ fields.append(Field('major_update'))
+
+ fields.extend([
Field('pubdate'),
ButtonHolder(
StrictButton(_(u'Enregistrer'), type='submit'),
- ),
- )
+ )
+ ])
+
+ self.helper.layout = Layout(*fields)
class FeaturedMessageForm(forms.ModelForm):
diff --git a/zds/featured/tests.py b/zds/featured/tests.py
index c2b0fe64b5..a2ffc4edeb 100644
--- a/zds/featured/tests.py
+++ b/zds/featured/tests.py
@@ -6,6 +6,7 @@
from zds.member.factories import StaffProfileFactory, ProfileFactory
from zds.featured.factories import FeaturedResourceFactory
from zds.featured.models import FeaturedResource, FeaturedMessage
+from datetime import datetime, date
stringof2001chars = 'http://url.com/'
@@ -52,25 +53,44 @@ def test_success_create_featured(self):
username=staff.user.username,
password='hostel77'
)
- self.assertTrue(login_check)
+ self.assertTrue(login_check)
self.assertEqual(0, FeaturedResource.objects.all().count())
- response = self.client.post(
- reverse('featured-resource-create'),
- {
- 'title': 'title',
- 'type': 'type',
- 'image_url': 'image_url',
- 'url': 'url',
- 'authors': staff.user.username,
- 'pubdate': '2016-12-25 00:00:00'
- },
- follow=True
- )
+
+ pubdate = date(2016, 1, 1).strftime('%d/%m/%Y %H:%M:%S')
+
+ fields = {
+ 'title': 'title',
+ 'type': 'type',
+ 'image_url': 'http://test.com/image.png',
+ 'url': 'http://test.com',
+ 'authors': staff.user.username,
+ 'pubdate': pubdate
+ }
+
+ response = self.client.post(reverse('featured-resource-create'), fields, follow=True)
self.assertEqual(200, response.status_code)
self.assertEqual(1, FeaturedResource.objects.all().count())
+ featured = FeaturedResource.objects.first()
+
+ for field, value in fields.items():
+ if field != 'pubdate':
+ self.assertEqual(value, getattr(featured, field), msg='Error on {}'.format(field))
+ else:
+ self.assertEqual(value, featured.pubdate.strftime('%d/%m/%Y %H:%M:%S'))
+
+ # now with major_update
+ fields['major_update'] = 'on'
+
+ response = self.client.post(reverse('featured-resource-create'), fields, follow=True)
+ self.assertEqual(200, response.status_code)
+ self.assertEqual(2, FeaturedResource.objects.all().count())
+
+ featured = FeaturedResource.objects.last()
+ self.assertTrue((datetime.now() - featured.pubdate).total_seconds() < 10)
+
def test_failure_create_featured_with_unauthenticated_user(self):
response = self.client.get(reverse('featured-resource-create'))
@@ -103,7 +123,7 @@ def test_failure_too_long_url(self):
'title': 'title',
'type': 'type',
'image_url': stringof2001chars,
- 'url': 'url',
+ 'url': 'http://test.com',
'authors': staff.user.username
},
follow=True
@@ -117,7 +137,7 @@ def test_failure_too_long_url(self):
{
'title': 'title',
'type': 'type',
- 'image_url': 'url',
+ 'image_url': 'http://test.com/image.png',
'url': stringof2001chars,
'authors': staff.user.username
},
@@ -139,21 +159,45 @@ def test_success_update_featured(self):
news = FeaturedResourceFactory()
self.assertEqual(1, FeaturedResource.objects.all().count())
- response = self.client.post(
- reverse('featured-resource-update', args=[news.pk]),
- {
- 'title': 'title',
- 'type': 'type',
- 'image_url': 'image_url',
- 'url': 'url',
- 'authors': staff.user.username
- },
- follow=True
- )
+
+ old_featured = FeaturedResource.objects.first()
+
+ pubdate = date(2016, 1, 1).strftime('%d/%m/%Y %H:%M:%S')
+
+ fields = {
+ 'title': 'title',
+ 'type': 'type',
+ 'image_url': 'http://test.com/image.png',
+ 'url': 'http://test.com',
+ 'authors': staff.user.username,
+ 'pubdate': pubdate
+ }
+
+ response = self.client.post(reverse('featured-resource-update', args=[news.pk]), fields, follow=True)
self.assertEqual(200, response.status_code)
self.assertEqual(1, FeaturedResource.objects.all().count())
+ featured = FeaturedResource.objects.first()
+
+ for field, value in fields.items():
+ self.assertNotEqual(getattr(featured, field), getattr(old_featured, field))
+
+ if field != 'pubdate':
+ self.assertEqual(value, getattr(featured, field), msg='Error on {}'.format(field))
+ else:
+ self.assertEqual(value, featured.pubdate.strftime('%d/%m/%Y %H:%M:%S'))
+
+ # now with major_update
+ self.assertFalse((datetime.now() - featured.pubdate).total_seconds() < 10)
+
+ fields['major_update'] = 'on'
+
+ response = self.client.post(reverse('featured-resource-update', args=[news.pk]), fields, follow=True)
+ self.assertEqual(200, response.status_code)
+ featured = FeaturedResource.objects.first()
+ self.assertTrue((datetime.now() - featured.pubdate).total_seconds() < 10)
+
def test_failure_create_featured_with_unauthenticated_user(self):
response = self.client.get(reverse('featured-resource-update', args=[42]))
@@ -266,7 +310,7 @@ def test_success_list_create_message(self):
reverse('featured-message-create'),
{
'message': 'message',
- 'url': 'url',
+ 'url': 'http://test.com',
},
follow=True
)
@@ -286,7 +330,7 @@ def test_create_only_one_message_in_system(self):
reverse('featured-message-create'),
{
'message': 'message',
- 'url': 'url',
+ 'url': 'http://test.com',
},
follow=True
)
@@ -298,7 +342,7 @@ def test_create_only_one_message_in_system(self):
reverse('featured-message-create'),
{
'message': 'message',
- 'url': 'url',
+ 'url': 'http://test.com',
},
follow=True
)
diff --git a/zds/featured/views.py b/zds/featured/views.py
index 94ab9150e5..3462c931b1 100644
--- a/zds/featured/views.py
+++ b/zds/featured/views.py
@@ -5,11 +5,10 @@
from django.contrib.auth.decorators import login_required, permission_required
from django.core.urlresolvers import reverse
from django.db import transaction
-from django.shortcuts import render, redirect
+from django.shortcuts import redirect
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
-from django.views.generic import CreateView, RedirectView, UpdateView
-from django.views.generic.detail import SingleObjectMixin
+from django.views.generic import CreateView, RedirectView, UpdateView, FormView, DeleteView
from django.views.generic.list import MultipleObjectMixin
from django.conf import settings
@@ -41,31 +40,34 @@ class FeaturedResourceCreate(CreateView):
form_class = FeaturedResourceForm
template_name = 'featured/resource/create.html'
+ context_object_name = 'featured_resource'
@method_decorator(login_required)
@method_decorator(permission_required('featured.change_featuredresource', raise_exception=True))
def dispatch(self, request, *args, **kwargs):
return super(FeaturedResourceCreate, self).dispatch(request, *args, **kwargs)
- def post(self, request, *args, **kwargs):
- form = self.form_class(request.POST)
-
- if form.is_valid():
- return self.form_valid(form)
-
- return render(request, self.template_name, {'form': form})
+ def get_form_kwargs(self):
+ kw = super(FeaturedResourceCreate, self).get_form_kwargs()
+ kw['hide_major_update_field'] = True
+ return kw
def form_valid(self, form):
-
featured_resource = FeaturedResource()
- featured_resource.title = form.data.get('title')
- featured_resource.type = form.data.get('type')
- featured_resource.authors = form.data.get('authors')
- featured_resource.image_url = form.data.get('image_url')
- featured_resource.url = form.data.get('url')
- featured_resource.pubdate = form.data.get('pubdate')
+ featured_resource.title = form.cleaned_data.get('title')
+ featured_resource.type = form.cleaned_data.get('type')
+ featured_resource.authors = form.cleaned_data.get('authors')
+ featured_resource.image_url = form.cleaned_data.get('image_url')
+ featured_resource.url = form.cleaned_data.get('url')
+
+ if form.cleaned_data.get('major_update', False):
+ featured_resource.pubdate = datetime.now()
+ else:
+ featured_resource.pubdate = form.cleaned_data.get('pubdate')
+
featured_resource.save()
+ messages.success(self.request, _(u'La une a été créée.'))
return redirect(reverse('featured-resource-list'))
@@ -77,74 +79,66 @@ class FeaturedResourceUpdate(UpdateView):
form_class = FeaturedResourceForm
template_name = 'featured/resource/update.html'
queryset = FeaturedResource.objects.all()
- featured_resource = None
+ context_object_name = 'featured_resource'
@method_decorator(login_required)
@method_decorator(permission_required('featured.change_featuredresource', raise_exception=True))
def dispatch(self, request, *args, **kwargs):
return super(FeaturedResourceUpdate, self).dispatch(request, *args, **kwargs)
- def get(self, request, *args, **kwargs):
- self.featured_resource = self.get_object()
- form = self.form_class(initial={
- 'title': self.featured_resource.title,
- 'type': self.featured_resource.type,
- 'authors': self.featured_resource.authors,
- 'image_url': self.featured_resource.image_url,
- 'url': self.featured_resource.url,
- 'pubdate': self.featured_resource.pubdate,
+ def get_initial(self):
+ initial = super(FeaturedResourceUpdate, self).get_initial()
+ initial.update({
+ 'title': self.object.title,
+ 'type': self.object.type,
+ 'authors': self.object.authors,
+ 'image_url': self.object.image_url,
+ 'url': self.object.url,
+ 'pubdate': self.object.pubdate,
})
- form.helper.form_action = reverse('featured-resource-update', args=[self.featured_resource.pk])
- return render(request, self.template_name, {'form': form, 'featured_resource': self.featured_resource})
- def post(self, request, *args, **kwargs):
- self.featured_resource = self.get_object()
- form = self.form_class(request.POST)
-
- if form.is_valid():
- return self.form_valid(form)
-
- return render(request, self.template_name, {'form': form, 'featured_resource': self.featured_resource})
+ return initial
def form_valid(self, form):
- self.featured_resource.title = form.data.get('title')
- self.featured_resource.type = form.data.get('type')
- self.featured_resource.authors = form.data.get('authors')
- self.featured_resource.image_url = form.data.get('image_url')
- self.featured_resource.url = form.data.get('url')
- if form.data.get('major_update') is not None:
- self.featured_resource.pubdate = datetime.now()
-
- self.featured_resource.save()
- return redirect(reverse('homepage'))
-
- def get_form(self, form_class=FeaturedResourceForm):
- form = self.form_class(self.request.POST)
- form.helper.form_action = reverse('featured-resource-update', args=[self.featured_resource.pk])
+ self.object.title = form.cleaned_data.get('title')
+ self.object.type = form.cleaned_data.get('type')
+ self.object.authors = form.cleaned_data.get('authors')
+ self.object.image_url = form.cleaned_data.get('image_url')
+ self.object.url = form.cleaned_data.get('url')
+ if form.cleaned_data.get('major_update', False):
+ self.object.pubdate = datetime.now()
+ else:
+ self.object.pubdate = form.cleaned_data.get('pubdate')
+
+ messages.success(self.request, _(u'La une a été mise à jour.'))
+ self.success_url = reverse('featured-resource-list')
+ return super(FeaturedResourceUpdate, self).form_valid(form)
+
+ def get_form(self, form_class=None):
+ form = super(FeaturedResourceUpdate, self).get_form(form_class)
+ form.helper.form_action = reverse('featured-resource-update', args=[self.object.pk])
return form
-class FeaturedResourceDeleteDetail(SingleObjectMixin, RedirectView):
+class FeaturedResourceDeleteDetail(DeleteView):
"""
Deletes a featured resource.
"""
- queryset = FeaturedResource.objects.all()
- permanent = False
+
+ model = FeaturedResource
@method_decorator(login_required)
@method_decorator(transaction.atomic)
@method_decorator(permission_required('featured.change_featuredresource', raise_exception=True))
def dispatch(self, request, *args, **kwargs):
+ self.success_url = reverse('featured-resource-list')
return super(FeaturedResourceDeleteDetail, self).dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
- featured_resource = self.get_object()
- featured_resource.delete()
-
+ r = super(FeaturedResourceDeleteDetail, self).post(request, *args, **kwargs)
messages.success(request, _(u'La une a été supprimée avec succès.'))
-
- return redirect(reverse('featured-resource-list'))
+ return r
class FeaturedResourceDeleteList(MultipleObjectMixin, RedirectView):
@@ -171,48 +165,42 @@ def post(self, request, *args, **kwargs):
return redirect(reverse('featured-resource-list'))
-class FeaturedMessageCreateUpdate(CreateView):
+class FeaturedMessageCreateUpdate(FormView):
"""
Creates or updates the featured message.
"""
form_class = FeaturedMessageForm
template_name = 'featured/message/create.html'
+ last_message = None
@method_decorator(login_required)
@method_decorator(permission_required('featured.change_featuredmessage', raise_exception=True))
def dispatch(self, request, *args, **kwargs):
+ self.last_message = FeaturedMessage.objects.get_last_message()
return super(FeaturedMessageCreateUpdate, self).dispatch(request, *args, **kwargs)
- def get(self, request, *args, **kwargs):
- last_message = FeaturedMessage.objects.get_last_message()
- init = {}
- if last_message is not None:
- init = {
- 'hook': last_message.hook,
- 'message': last_message.message,
- 'url': last_message.url,
- }
+ def get_initial(self):
+ init = super(FeaturedMessageCreateUpdate, self).get_initial()
- form = self.form_class(initial=init)
- form.helper.form_action = reverse('featured-message-create')
- return render(request, self.template_name, {'form': form})
+ if self.last_message is not None:
+ init.update({
+ 'hook': self.last_message.hook,
+ 'message': self.last_message.message,
+ 'url': self.last_message.url,
+ })
- def post(self, request, *args, **kwargs):
- form = self.form_class(request.POST)
-
- if form.is_valid():
- return self.form_valid(form)
-
- return render(request, self.template_name, {'form': form})
+ return init
def form_valid(self, form):
- last_message = FeaturedMessage.objects.get_last_message()
- if last_message:
- last_message.delete()
+ if self.last_message:
+ self.last_message.delete()
+
featured_message = FeaturedMessage()
featured_message.hook = form.data.get('hook')
featured_message.message = form.data.get('message')
featured_message.url = form.data.get('url')
featured_message.save()
- return redirect(reverse('homepage'))
+
+ messages.success(self.request, _(u'Le message a été changé'))
+ return redirect(reverse('featured-resource-list'))