From 4d8bfc1b2fb606bc7d7bb0f305e98d73eba0439c Mon Sep 17 00:00:00 2001 From: Tim Heap Date: Wed, 12 Oct 2016 10:36:53 +1100 Subject: [PATCH] Start the page chooser at the most relevant page Using the new `Page.objects.first_common_ancestor()`, page choosers that are restricted to a certain page type start at the most relevant parent page to make selecting a page easier. --- .../wagtailadmin/tests/test_page_chooser.py | 78 +++++++++++++++++++ wagtail/wagtailadmin/views/chooser.py | 28 ++++--- 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/wagtail/wagtailadmin/tests/test_page_chooser.py b/wagtail/wagtailadmin/tests/test_page_chooser.py index 992ae9d67..71796c516 100644 --- a/wagtail/wagtailadmin/tests/test_page_chooser.py +++ b/wagtail/wagtailadmin/tests/test_page_chooser.py @@ -298,6 +298,84 @@ class TestChooserSearch(TestCase, WagtailTestUtils): self.assertEqual(response.status_code, 404) +class TestAutomaticRootPageDetection(TestCase, WagtailTestUtils): + def setUp(self): + self.tree_root = Page.objects.get(id=1) + self.home_page = Page.objects.get(id=2) + + self.about_page = self.home_page.add_child(instance=SimplePage( + title='About', content='About Foo')) + self.contact_page = self.about_page.add_child(instance=SimplePage( + title='Contact', content='Content Foo')) + self.people_page = self.about_page.add_child(instance=SimplePage( + title='People', content='The people of Foo')) + + self.event_index = self.make_event_section('Events') + + self.login() + + def make_event_section(self, name): + event_index = self.home_page.add_child(instance=EventIndex( + title=name)) + event_index.add_child(instance=EventPage( + title='First Event', + location='Bar', audience='public', + cost='free', date_from='2001-01-01')) + event_index.add_child(instance=EventPage( + title='Second Event', + location='Baz', audience='public', + cost='free', date_from='2001-01-01')) + return event_index + + def get_best_root(self, params={}): + response = self.client.get(reverse('wagtailadmin_choose_page'), params) + return response.context['parent_page'].specific + + def test_no_type_filter(self): + self.assertEqual(self.get_best_root(), self.tree_root) + + def test_type_page(self): + self.assertEqual( + self.get_best_root({'page_type': 'wagtailcore.Page'}), + self.tree_root) + + def test_type_eventpage(self): + """ + The chooser should start at the EventIndex that holds all the + EventPages. + """ + self.assertEqual( + self.get_best_root({'page_type': 'tests.EventPage'}), + self.event_index) + + def test_type_eventpage_two_indexes(self): + """ + The chooser should start at the home page, as there are two + EventIndexes with EventPages. + """ + self.make_event_section('Other events') + self.assertEqual( + self.get_best_root({'page_type': 'tests.EventPage'}), + self.home_page) + + def test_type_simple_page(self): + """ + The chooser should start at the home page, as all SimplePages are + directly under it + """ + self.assertEqual( + self.get_best_root({'page_type': 'tests.BusinessIndex'}), + self.tree_root) + + def test_type_missing(self): + """ + The chooser should start at the root, as there are no BusinessIndexes + """ + self.assertEqual( + self.get_best_root({'page_type': 'tests.BusinessIndex'}), + self.tree_root) + + class TestChooserExternalLink(TestCase, WagtailTestUtils): def setUp(self): self.login() diff --git a/wagtail/wagtailadmin/views/chooser.py b/wagtail/wagtailadmin/views/chooser.py index eddfd369c..473a45314 100644 --- a/wagtail/wagtailadmin/views/chooser.py +++ b/wagtail/wagtailadmin/views/chooser.py @@ -51,32 +51,38 @@ def filter_page_type(queryset, page_models): def browse(request, parent_page_id=None): + # A missing or empty page_type parameter indicates 'all page types' + # (i.e. descendants of wagtailcore.page) + page_type_string = request.GET.get('page_type') or 'wagtailcore.page' + try: + desired_classes = page_models_from_string(page_type_string) + except (ValueError, LookupError): + raise Http404 + # Find parent page if parent_page_id: parent_page = get_object_or_404(Page, id=parent_page_id) - else: + elif desired_classes == (Page,): + # Just use the root page parent_page = Page.get_first_root_node() + else: + # Find the highest common ancestor for the specific classes passed in + # In many cases, such as selecting an EventPage under an EventIndex, + # this will help the administrator find their page quicker. + all_desired_pages = filter_page_type(Page.objects.all(), desired_classes) + parent_page = all_desired_pages.first_common_ancestor() # Get children of parent page pages = parent_page.get_children() # Filter them by page type - # A missing or empty page_type parameter indicates 'all page types' (i.e. descendants of wagtailcore.page) - page_type_string = request.GET.get('page_type') or 'wagtailcore.page' - if page_type_string != 'wagtailcore.page': - try: - desired_classes = page_models_from_string(page_type_string) - except (ValueError, LookupError): - raise Http404 - + if desired_classes != (Page,): # restrict the page listing to just those pages that: # - are of the given content type (taking into account class inheritance) # - or can be navigated into (i.e. have children) choosable_pages = filter_page_type(pages, desired_classes) descendable_pages = pages.filter(numchild__gt=0) pages = choosable_pages | descendable_pages - else: - desired_classes = (Page, ) can_choose_root = request.GET.get('can_choose_root', False)