From 18560c419bff9e7b1fd704aa6ebf3d761b2aa2a7 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Mon, 17 Jan 2022 13:44:38 +0100 Subject: [PATCH 1/5] data: add max_one_by_page cell class attribute (#60547) --- combo/data/models.py | 2 ++ combo/manager/views.py | 11 +++++++++-- tests/test_manager.py | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/combo/data/models.py b/combo/data/models.py index bd7ff67c..ef0c81b3 100644 --- a/combo/data/models.py +++ b/combo/data/models.py @@ -792,6 +792,7 @@ class CellBase(models.Model, metaclass=CellMeta): visible = True user_dependant = False default_template_name = None + max_one_by_page = False # get_badge(self, context); set to None so cell types can be skipped easily get_badge = None @@ -1030,6 +1031,7 @@ class CellBase(models.Model, metaclass=CellMeta): 'group': cls.get_cell_type_group(), 'variant': 'default', 'order': 0, + 'max_one_by_page': cls.max_one_by_page, } ] diff --git a/combo/manager/views.py b/combo/manager/views.py index 18802835..629e3816 100644 --- a/combo/manager/views.py +++ b/combo/manager/views.py @@ -372,10 +372,14 @@ class PageView(ManagedPageMixin, DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + cells = CellBase.get_cells(page=self.object, prefetch_validity_info=True) + existing_cell_types = {cell.get_cell_type_str() for cell in cells} cell_type_groups = {} for cell_type in CellBase.get_all_cell_types(): if not cell_type['group'] in cell_type_groups: cell_type_groups[cell_type['group']] = [] + if cell_type.get('max_one_by_page') and cell_type['cell_type_str'] in existing_cell_types: + continue cell_type_groups[cell_type['group']].append(cell_type) for cell_group in cell_type_groups.values(): cell_group.sort(key=lambda x: (x.get('order'), x.get('name'))) @@ -386,7 +390,6 @@ class PageView(ManagedPageMixin, DetailView): context['cell_type_groups'].sort(key=lambda x: x[0]) context['page_has_subpages'] = self.object.get_children().exists() - cells = CellBase.get_cells(page=self.object, prefetch_validity_info=True) self.object.prefetched_cells = cells placeholders = [] optional_placeholders = [] @@ -604,10 +607,14 @@ class PageAddCellView(ManagedPageMixin, RedirectView): permanent = False def get_redirect_url(self, page_pk, cell_type, variant, ph_key): + page_cells = CellBase.get_cells(page_id=page_pk) cell_class = get_cell_class(cell_type) + if cell_class.max_one_by_page and any(isinstance(x, cell_class) for x in page_cells): + raise PermissionDenied() + cell = cell_class(page_id=page_pk, placeholder=ph_key) cell.set_variant(variant) - orders = [x.order for x in CellBase.get_cells(page_id=page_pk)] + orders = [x.order for x in page_cells] if orders: cell.order = max(orders) + 1 else: diff --git a/tests/test_manager.py b/tests/test_manager.py index 5d05f35f..9226c29f 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -1249,6 +1249,27 @@ def test_add_all_basic_cell_types(app, admin_user): resp = resp.follow() +@mock.patch('combo.data.models.TextCell.max_one_by_page', mock.PropertyMock(return_value=True)) +def test_add_cell_max_one_by_page(app, admin_user): + page = Page.objects.create(title='One', slug='one', template_name='standard') + app = login(app) + resp = app.get('/manage/pages/%s/' % page.id) + + add_text_cell_url = resp.html.find('option').get('data-add-url') + resp = app.get(add_text_cell_url) + + cells = CellBase.get_cells(page_id=page.id) + assert len(cells) == 1 + assert isinstance(cells[0], TextCell) + assert resp.location.endswith('/manage/pages/%s/#cell-%s' % (page.id, cells[0].get_reference())) + + resp = app.get('/manage/pages/%s/' % page.id) + assert not add_text_cell_url in resp.text + + # try to add cell anyway + resp = app.get(add_text_cell_url, status=403) + + SEARCH_SERVICES = { 'search1': { 'label': 'Search 1', -- 2.30.2