Skip to content

Commit

Permalink
fix: When opening structure board page menu disappears or shows wrong…
Browse files Browse the repository at this point in the history
… page template (#7671)

* Fix: add .current_page to request for structure board

* Fix caching issue showing wrong selected page template

* Fix: add .current_page to request for structure board

* Fix caching issue showing wrong selected page template

* Add tests

* fix: Update RTD config (#7647)

* Add comments

---------

Co-authored-by: Mark Walker <mark@django-cms.org>
  • Loading branch information
fsbraun and marksweb committed Oct 17, 2023
1 parent f572e38 commit 160669e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 14 deletions.
20 changes: 20 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2

build:
os: ubuntu-22.04
tools:
python: "3.11"

sphinx:
configuration: docs/conf.py
fail_on_warning: false

formats:
- epub
- pdf

python:
install:
- requirements: docs/requirements.txt
46 changes: 35 additions & 11 deletions cms/cms_toolbars.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from cms.api import can_change_page
from cms.constants import TEMPLATE_INHERITANCE_MAGIC
from cms.models import Page, PageType, Placeholder
from cms.models import Page, PageContent, PageType, Placeholder
from cms.toolbar.items import REFRESH_PAGE, ButtonList, TemplateItem
from cms.toolbar.utils import (
get_object_edit_url,
Expand Down Expand Up @@ -383,6 +383,13 @@ class PageToolbar(CMSToolbar):
watch_models = [Page, PageType]

def get_page_content(self):
if not getattr(self, "page", None):
# No page, no page content
return None
if hasattr(self, "obj") and isinstance(self.obj, PageContent):
# Toolbar object already set (e.g., in edit or preview mode)
return self.obj
# Get from db
page_content = self.page.get_content_obj(language=self.current_lang, fallback=False)
return page_content or None

Expand Down Expand Up @@ -428,11 +435,28 @@ def get_on_delete_redirect_url(self):
# page, if DEBUG == False this could cause a 404
return reverse('pages-root')

# Populate
@property
def title(self):
import warnings

warnings.warn(
"Title property of PageToolbar will be removed. Use page_content property instead.",
DeprecationWarning, stacklevel=2)
return self.page_content

@title.setter
def title(self, page_content):
import warnings

warnings.warn(
"Title property of PageToolbar will be removed. Use page_content property instead.",
DeprecationWarning, stacklevel=2)
self.page_content = page_content

# Populate
def populate(self):
self.page = self.request.current_page
self.title = self.get_page_content() if self.page else None
self.page_content = self.get_page_content()
self.permissions_activated = get_cms_setting('PERMISSION')
self.change_admin_menu()
self.add_page_menu()
Expand Down Expand Up @@ -526,7 +550,7 @@ def change_admin_menu(self):
self._changed_admin_menu = True

def add_page_menu(self):
if self.page and self.title:
if self.page and self.page_content:
edit_mode = self.toolbar.edit_mode_active
refresh = self.toolbar.REFRESH_PAGE
can_change = user_can_change_page(
Expand All @@ -548,8 +572,8 @@ def add_page_menu(self):

add_page_url = admin_reverse('cms_pagecontent_add')
advanced_url = admin_reverse('cms_page_advanced', args=(self.page.pk,))
page_settings_url = admin_reverse('cms_pagecontent_change', args=(self.title.pk,))
duplicate_page_url = admin_reverse('cms_pagecontent_duplicate', args=[self.title.pk])
page_settings_url = admin_reverse('cms_pagecontent_change', args=(self.page_content.pk,))
duplicate_page_url = admin_reverse('cms_pagecontent_duplicate', args=[self.page_content.pk])

can_add_root_page = page_permissions.user_can_add_page(
user=self.request.user,
Expand Down Expand Up @@ -600,7 +624,7 @@ def add_page_menu(self):

# page edit
with force_language(self.current_lang):
page_edit_url = get_object_edit_url(self.title) if self.title else ''
page_edit_url = get_object_edit_url(self.page_content) if self.page_content else ''
current_page_menu.add_link_item(_('Edit this Page'), disabled=edit_mode, url=page_edit_url)

# page settings
Expand All @@ -617,7 +641,7 @@ def add_page_menu(self):

# templates menu
if edit_mode:
action = admin_reverse('cms_pagecontent_change_template', args=(self.title.pk,))
action = admin_reverse('cms_pagecontent_change_template', args=(self.page_content.pk,))

if can_change_advanced:
templates_menu = current_page_menu.get_or_create_menu(
Expand All @@ -627,16 +651,16 @@ def add_page_menu(self):
)

for path, name in get_cms_setting('TEMPLATES'):
active = self.page.template == path
active = self.page_content.template == path
if path == TEMPLATE_INHERITANCE_MAGIC:
templates_menu.add_break(TEMPLATE_MENU_BREAK)
templates_menu.add_ajax_item(name, action=action, data={'template': path}, active=active,
on_success=refresh)

# navigation toggle
in_navigation = self.title.in_navigation
in_navigation = self.page_content.in_navigation
nav_title = _('Hide in navigation') if in_navigation else _('Display in navigation')
nav_action = admin_reverse('cms_pagecontent_change_innavigation', args=(self.title.pk,))
nav_action = admin_reverse('cms_pagecontent_change_innavigation', args=(self.page_content.pk,))
current_page_menu.add_ajax_item(
nav_title,
action=nav_action,
Expand Down
30 changes: 27 additions & 3 deletions cms/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.http import Http404
from django.http import Http404, HttpResponse
from django.template import Variable
from django.test.utils import override_settings
from django.urls import clear_url_caches, reverse
from django.utils.translation import override as force_language

from cms.api import create_page, create_page_content
from cms.models import PagePermission, Placeholder, UserSettings
from cms.middleware.toolbar import ToolbarMiddleware
from cms.models import PageContent, PagePermission, Placeholder, UserSettings
from cms.page_rendering import _handle_no_page
from cms.test_utils.testcases import CMSTestCase
from cms.test_utils.util.fuzzy_int import FuzzyInt
Expand All @@ -23,7 +25,7 @@
)
from cms.utils.conf import get_cms_setting
from cms.utils.page import get_page_from_request
from cms.views import details, login
from cms.views import details, login, render_object_structure
from menus.menu_pool import menu_pool

APP_NAME = 'SampleApp'
Expand Down Expand Up @@ -388,3 +390,25 @@ def test_context_current_page(self):
response = self.client.get("/en/page-2/")
template = Variable('CMS_TEMPLATE').resolve(response.context)
self.assertEqual(template, page_template)

class EndpointTests(CMSTestCase):

def setUp(self) -> None:
page_template = "simple.html"
self.page = self.create_homepage("page", page_template, "en")
self.page_content = self.page.get_content_obj()
self.content_type = ContentType.objects.get_for_model(PageContent)
self.client.force_login(self.get_superuser())

def tearDown(self) -> None:
self.page.delete()

def test_render_object_structure(self):
request = self.get_request("/")
request.user = self.get_superuser()
mid = ToolbarMiddleware(lambda req: HttpResponse(""))
mid(request)
response = render_object_structure(request, self.content_type.id, self.page_content.pk)

self.assertEqual(request.current_page, self.page)
self.assertContains(response, '<div class="cms-toolbar">')
2 changes: 2 additions & 0 deletions cms/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ def render_object_structure(request, content_type_id, object_id):
'object': content_type_obj,
'cms_toolbar': request.toolbar,
}
if isinstance(content_type_obj, PageContent):
request.current_page = content_type_obj.page
toolbar = get_toolbar_from_request(request)
toolbar.set_object(content_type_obj)
return render(request, 'cms/toolbar/structure.html', context)
Expand Down

0 comments on commit 160669e

Please sign in to comment.