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'])