diff --git a/HISTORY.rst b/HISTORY.rst
index 0bcac81..b7f7856 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,12 +3,13 @@
History
-------
-0.6.4 (unreleased)
+0.7.0 (unreleased)
++++++++++++++++++
* Make categories non required
* Fix tests with parler>=1.6
* Use all_languages_column to admin
+* Add publish button
0.6.3 (2015-12-22)
++++++++++++++++++
diff --git a/djangocms_blog/admin.py b/djangocms_blog/admin.py
index 99df7c8..e48f3f6 100755
--- a/djangocms_blog/admin.py
+++ b/djangocms_blog/admin.py
@@ -7,9 +7,12 @@ from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
from django import forms
from django.conf import settings
+from django.conf.urls import url
from django.contrib import admin
+from django.core.urlresolvers import reverse
+from django.http import HttpResponseRedirect
from django.utils.six import callable
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import get_language_from_request, ugettext_lazy as _
from parler.admin import TranslatableAdmin
from .cms_appconfig import BlogConfig
@@ -73,8 +76,35 @@ class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
'default_published': 'publish'
}
- def languages(self, obj):
- return ','.join(obj.get_available_languages())
+ def get_urls(self):
+ """
+ Customize the modeladmin urls
+ """
+ urls = [
+ url(r'^publish/([0-9]+)/$', self.admin_site.admin_view(self.publish_post),
+ name='djangocms_blog_publish_article'),
+ ]
+ urls.extend(super(PostAdmin, self).get_urls())
+ return urls
+
+ def publish_post(self, request, pk):
+ """
+ Admin view to publish a single post
+ :param request: request
+ :param pk: primary key of the post to publish
+ :return: Redirect to the post itself (if found) or fallback urls
+ """
+ language = get_language_from_request(request, check_path=True)
+ try:
+ post = Post.objects.get(pk=int(pk))
+ post.publish = True
+ post.save()
+ return HttpResponseRedirect(post.get_absolute_url(language))
+ except Exception:
+ try:
+ return HttpResponseRedirect(request.META['HTTP_REFERER'])
+ except KeyError:
+ return HttpResponseRedirect(reverse('djangocms_blog:posts-latest'))
def formfield_for_dbfield(self, db_field, **kwargs):
field = super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
@@ -87,6 +117,12 @@ class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
return field
def get_fieldsets(self, request, obj=None):
+ """
+ Customize the fieldsets according to the app settings
+ :param request: request
+ :param obj: post
+ :return: fieldsets configuration
+ """
app_config_default = self._app_config_select(request, obj)
if app_config_default is None and request.method == 'GET':
return super(PostAdmin, self).get_fieldsets(request, obj)
@@ -132,6 +168,9 @@ class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin):
@property
def declared_fieldsets(self):
+ """
+ Fieldsets configuration
+ """
return [
(None, {
'fields': ('type', 'namespace', 'app_title', 'object_name')
diff --git a/djangocms_blog/cms_toolbar.py b/djangocms_blog/cms_toolbar.py
index b5d5d85..7dfd2cc 100644
--- a/djangocms_blog/cms_toolbar.py
+++ b/djangocms_blog/cms_toolbar.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import, print_function, unicode_literals
from cms.toolbar_base import CMSToolbar
from cms.toolbar_pool import toolbar_pool
+from cms.utils.urlutils import admin_reverse
from django.core.urlresolvers import reverse
from django.utils.translation import override, ugettext_lazy as _
@@ -33,6 +34,22 @@ class BlogToolbar(CMSToolbar):
'admin:djangocms_blog_post_change', args=(current_post.pk,)),
active=True)
+ def add_publish_button(self):
+ """
+ Adds the publish button to the toolbar if the current post is unpublished
+ """
+ current_post = getattr(self.request, get_setting('CURRENT_POST_IDENTIFIER'), None)
+ if (self.toolbar.edit_mode and current_post and
+ not current_post.publish and
+ self.request.user.has_perm('djangocms_blog.change_post')
+ ): # pragma: no cover # NOQA
+ classes = ['cms-btn-action', 'blog-publish']
+ title = _('Publish {0} now').format(current_post.app_config.object_name)
+
+ url = admin_reverse('djangocms_blog_publish_article', args=(current_post.pk,))
+
+ self.toolbar.add_button(title, url=url, extra_classes=classes, side=self.toolbar.RIGHT)
+
def post_template_populate(self):
current_post = getattr(self.request, get_setting('CURRENT_POST_IDENTIFIER'), None)
if current_post and self.request.user.has_perm('djangocms_blog.change_post'): # pragma: no cover # NOQA
@@ -52,3 +69,4 @@ class BlogToolbar(CMSToolbar):
menu.remove_item(pagetags)
except ImportError:
pass
+ self.add_publish_button()
diff --git a/tests/test_models.py b/tests/test_models.py
index fcce681..ab8977d 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -34,6 +34,8 @@ class AdminTest(BaseTest):
admin.autodiscover()
def test_admin_post_views(self):
+ self.get_pages()
+
post_admin = admin.site._registry[Post]
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
@@ -50,6 +52,28 @@ class AdminTest(BaseTest):
self.assertContains(response, '')
self.assertContains(response, '' % self.app_config_1.pk)
+ # Test for publish view
+ post.publish = False
+ post.save()
+ response = post_admin.publish_post(request, str(post.pk))
+ # Redirects to current post
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(response['Location'], post.get_absolute_url())
+ post = self.reload_model(post)
+ # post is publshed
+ self.assertTrue(post.publish)
+
+ # Non-existing post is redirected to posts list
+ response = post_admin.publish_post(request, str('1000000'))
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(response['Location'], reverse('djangocms_blog:posts-latest'))
+
+ # unless a referer is set
+ request.META['HTTP_REFERER'] = '/'
+ response = post_admin.publish_post(request, str('1000000'))
+ self.assertEqual(response.status_code, 302)
+ self.assertEqual(response['Location'], '/')
+
def test_admin_blogconfig_views(self):
post_admin = admin.site._registry[BlogConfig]
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
diff --git a/tests/test_toolbar.py b/tests/test_toolbar.py
index 90b6ccb..e3bc069 100644
--- a/tests/test_toolbar.py
+++ b/tests/test_toolbar.py
@@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals
-from cms.toolbar.items import ModalItem
+from cms.toolbar.items import ButtonList, ModalItem
from django.core.urlresolvers import reverse
+from django.utils.encoding import force_text
from djangocms_blog.models import BLOG_CURRENT_POST_IDENTIFIER
@@ -20,9 +21,39 @@ class ToolbarTest(BaseTest):
pages = self.get_pages()
request = self.get_page_request(pages[0], self.user, r'/en/blog/', edit=True)
setattr(request, BLOG_CURRENT_POST_IDENTIFIER, posts[0])
+
+ posts[0].publish = False
+ posts[0].save()
toolbar = CMSToolbar(request)
+ toolbar.populate()
+ toolbar.post_template_populate()
toolbar.get_left_items()
blog_menu = toolbar.menus['djangocms_blog']
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_changelist'))), 1)
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_add'))), 1)
self.assertEqual(len(blog_menu.find_items(ModalItem, url=reverse('admin:djangocms_blog_post_change', args=(posts[0].pk,)))), 1)
+
+ # Publish button only appears if current post is unpublished
+ right = toolbar.get_right_items()
+ buttons = sum([item.buttons for item in right if isinstance(item, ButtonList)], [])
+ self.assertTrue([button for button in buttons if force_text(button.name) == 'Publish Blog now'])
+
+ # Publish button does not appears if current post is published
+ posts[0].publish = True
+ posts[0].save()
+ toolbar = CMSToolbar(request)
+ toolbar.populate()
+ toolbar.post_template_populate()
+ right = toolbar.get_right_items()
+ buttons = sum([item.buttons for item in right if isinstance(item, ButtonList)], [])
+ self.assertFalse([button for button in buttons if force_text(button.name) == 'Publish Blog now'])
+
+ # Publish button does not appears if other posts but the current one are unpublished
+ posts[1].publish = True
+ posts[1].save()
+ toolbar = CMSToolbar(request)
+ toolbar.populate()
+ toolbar.post_template_populate()
+ right = toolbar.get_right_items()
+ buttons = sum([item.buttons for item in right if isinstance(item, ButtonList)], [])
+ self.assertFalse([button for button in buttons if force_text(button.name) == 'Publish Blog now'])