From 5cc0e3fd623929fa300e10a5919c33d7c8f97e60 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Mon, 23 Feb 2015 14:47:29 +0000 Subject: [PATCH 1/3] Allow specifying custom edit handlers for pages - fixes #210 --- wagtail/tests/models.py | 14 ++++++++++- .../wagtailadmin/tests/test_pages_views.py | 21 +++++++++++++++++ wagtail/wagtailadmin/views/pages.py | 23 +++++++++++++++---- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/wagtail/tests/models.py b/wagtail/tests/models.py index 2169ef209..274a0b043 100644 --- a/wagtail/tests/models.py +++ b/wagtail/tests/models.py @@ -12,7 +12,7 @@ from modelcluster.tags import ClusterTaggableManager from wagtail.wagtailcore.models import Page, Orderable from wagtail.wagtailcore.fields import RichTextField -from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel, PageChooserPanel +from wagtail.wagtailadmin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel, PageChooserPanel, TabbedInterface, ObjectList from wagtail.wagtailimages.edit_handlers import ImageChooserPanel from wagtail.wagtaildocs.edit_handlers import DocumentChooserPanel from wagtail.wagtailforms.models import AbstractEmailForm, AbstractFormField @@ -390,15 +390,27 @@ class StandardIndex(Page): parent_page_types = [] +# A custom panel setup where all Promote fields are placed in the Content tab instead; +# we use this to test that the 'promote' tab is left out of the output when empty StandardIndex.content_panels = [ FieldPanel('title', classname="full title"), + FieldPanel('seo_title'), + FieldPanel('slug'), InlinePanel('advert_placements', label="Adverts"), ] +StandardIndex.promote_panels = [] class StandardChild(Page): pass +# Test overriding edit_handler with a custom one +StandardChild.edit_handler = TabbedInterface([ + ObjectList(StandardChild.content_panels, heading='Content'), + ObjectList(StandardChild.promote_panels, heading='Promote'), + ObjectList(StandardChild.settings_panels, heading='Settings', classname='settings'), + ObjectList([], heading='Dinosaurs'), +]) class BusinessIndex(Page): """ Can be placed anywhere, can only have Business children """ diff --git a/wagtail/wagtailadmin/tests/test_pages_views.py b/wagtail/wagtailadmin/tests/test_pages_views.py index de8b2fb2b..be6cc6a26 100644 --- a/wagtail/wagtailadmin/tests/test_pages_views.py +++ b/wagtail/wagtailadmin/tests/test_pages_views.py @@ -158,6 +158,27 @@ class TestPageCreation(TestCase, WagtailTestUtils): def test_create_simplepage(self): response = self.client.get(reverse('wagtailadmin_pages_create', args=('tests', 'simplepage', self.root_page.id))) self.assertEqual(response.status_code, 200) + self.assertContains(response, 'Content') + self.assertContains(response, 'Promote') + + def test_create_page_without_promote_tab(self): + """ + Test that the Promote tab is not rendered for page classes that define it as empty + """ + response = self.client.get(reverse('wagtailadmin_pages_create', args=('tests', 'standardindex', self.root_page.id))) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'Content') + self.assertNotContains(response, 'Promote') + + def test_create_page_with_custom_tabs(self): + """ + Test that custom edit handlers are rendered + """ + response = self.client.get(reverse('wagtailadmin_pages_create', args=('tests', 'standardchild', self.root_page.id))) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'Content') + self.assertContains(response, 'Promote') + self.assertContains(response, 'Dinosaurs') def test_create_simplepage_bad_permissions(self): # Remove privileges from user diff --git a/wagtail/wagtailadmin/views/pages.py b/wagtail/wagtailadmin/views/pages.py index a9c5c6fe5..f4c5c675d 100644 --- a/wagtail/wagtailadmin/views/pages.py +++ b/wagtail/wagtailadmin/views/pages.py @@ -707,11 +707,24 @@ PAGE_EDIT_HANDLERS = {} def get_page_edit_handler(page_class): if page_class not in PAGE_EDIT_HANDLERS: - PAGE_EDIT_HANDLERS[page_class] = TabbedInterface([ - ObjectList(page_class.content_panels, heading='Content'), - ObjectList(page_class.promote_panels, heading='Promote'), - ObjectList(page_class.settings_panels, heading='Settings', classname="settings") - ]).bind_to_model(page_class) + if hasattr(page_class, 'edit_handler'): + # use the edit handler specified on the page class + edit_handler = page_class.edit_handler + else: + # construct a TabbedInterface made up of content_panels, promote_panels + # and settings_panels, skipping any which are empty + tabs = [] + + if page_class.content_panels: + tabs.append(ObjectList(page_class.content_panels, heading='Content')) + if page_class.promote_panels: + tabs.append(ObjectList(page_class.promote_panels, heading='Promote')) + if page_class.settings_panels: + tabs.append(ObjectList(page_class.settings_panels, heading='Settings', classname="settings")) + + edit_handler = TabbedInterface(tabs) + + PAGE_EDIT_HANDLERS[page_class] = edit_handler.bind_to_model(page_class) return PAGE_EDIT_HANDLERS[page_class] From de2dc3d786e6ee990b85fc3c140f08c1c54ceabd Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Tue, 24 Feb 2015 11:52:05 +0000 Subject: [PATCH 2/3] documentation for #1022 --- docs/core_components/pages/editing_api.rst | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/core_components/pages/editing_api.rst b/docs/core_components/pages/editing_api.rst index 3c5c790d0..282667054 100644 --- a/docs/core_components/pages/editing_api.rst +++ b/docs/core_components/pages/editing_api.rst @@ -376,6 +376,40 @@ For more on ``django-modelcluster``, visit `the django-modelcluster github proje .. _the django-modelcluster github project page: https://github.com/torchbox/django-modelcluster +.. _customising_the_tabbed_interface: + +Customising the tabbed interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 0.9 + +As standard, Wagtail organises panels into three tabs: 'Content', 'Promote' and 'Settings'. Depending on the requirements of your site, you may wish to customise this for specific page types - for example, adding an additional tab for sidebar content. This can be done by specifying an ``edit_handler`` property on the page model. For example: + +.. code-block:: python + + from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList + + class BlogPage(Page): + # field definitions omitted + + BlogPage.content_panels = [ + FieldPanel('title', classname="full title"), + FieldPanel('date'), + FieldPanel('body', classname="full"), + ] + BlogPage.sidebar_content_panels = [ + SnippetChooserPanel('advert', Advert), + InlinePanel(BlogPage, 'related_links', label="Related links"), + ] + + BlogPage.edit_handler = TabbedInterface([ + ObjectList(BlogPage.content_panels, heading='Content'), + ObjectList(BlogPage.sidebar_content_panels, heading='Sidebar content'), + ObjectList(BlogPage.promote_panels, heading='Promote'), + ObjectList(BlogPage.settings_panels, heading='Settings', classname="settings"), + ]) + + .. _extending_wysiwyg: Extending the WYSIWYG Editor (hallo.js) From 87de5d0c663d91e39b3300eb2ae55113e158a036 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Wed, 25 Feb 2015 10:51:32 +0000 Subject: [PATCH 3/3] update InlinePanel syntax --- docs/core_components/pages/editing_api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core_components/pages/editing_api.rst b/docs/core_components/pages/editing_api.rst index 282667054..a228421ea 100644 --- a/docs/core_components/pages/editing_api.rst +++ b/docs/core_components/pages/editing_api.rst @@ -399,7 +399,7 @@ As standard, Wagtail organises panels into three tabs: 'Content', 'Promote' and ] BlogPage.sidebar_content_panels = [ SnippetChooserPanel('advert', Advert), - InlinePanel(BlogPage, 'related_links', label="Related links"), + InlinePanel('related_links', label="Related links"), ] BlogPage.edit_handler = TabbedInterface([