From 08faa44b40b1fd3509cbc114c506b847939e0208 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Wed, 21 Aug 2024 14:40:27 +0800 Subject: [PATCH 01/22] update for cms4.1 --- .github/workflows/test.yml | 3 ++- tests/requirements/dj42_cms41.txt | 21 +++++++++++++++++++++ tox.ini | 8 ++++---- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 tests/requirements/dj42_cms41.txt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 74ee428a5..b4de943e0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,10 +16,11 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ 3.8, 3.9, '3.10' ] + python-version: [ 3.9, '3.10' ] requirements-file: [ dj42_cms40.txt, dj32_cms40.txt, + dj42_cms41.txt, ] steps: diff --git a/tests/requirements/dj42_cms41.txt b/tests/requirements/dj42_cms41.txt new file mode 100644 index 000000000..52dd24ec3 --- /dev/null +++ b/tests/requirements/dj42_cms41.txt @@ -0,0 +1,21 @@ +beautifulsoup4 +coverage +django-app-helper +django-classy-tags +django-sekizai +factory_boy +flake8 +isort +lxml +tox + +django>=4.2,<5.0 +django-treebeard>=4.6.0 +django-cms>=4.1.0 +djangocms-text-ckeditor==5.1.5 +djangocms-versioning==2.0.2 +https://github.com/FreemanPancake/djangocms-version-locking/tarball/feature/djangocms4x-compat#egg=djangocms-version-locking +https://github.com/django-cms/djangocms-moderation/tarball/master#egg=djangocms-moderation +https://github.com/FidelityInternational/djangocms-references/tarball/release/1.5.0#egg=djangocms-references +https://github.com/django-cms/djangocms-alias/tarball/master#egg=djangocms-alias +https://github.com/joshyu/djangocms-snippet/tarball/master#egg=djangocms-snippet diff --git a/tox.ini b/tox.ini index bbf18d355..ed7e66636 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = flake8 isort - py{38,39,310}-dj{32,42}-sqlite-cms40 + py{39,310}-dj{32,42}-sqlite-cms{40,41} skip_missing_interpreters=True @@ -11,11 +11,11 @@ deps = flake8: -r{toxinidir}/tests/requirements/requirements_base.txt isort: -r{toxinidir}/tests/requirements/requirements_base.txt - dj32: -r{toxinidir}/tests/requirements/dj32_cms40.txt - dj42: -r{toxinidir}/tests/requirements/dj42_cms40.txt + dj32_cms40: -r{toxinidir}/tests/requirements/dj32_cms40.txt + dj42_cms40: -r{toxinidir}/tests/requirements/dj42_cms40.txt + dj42_cms41: -r{toxinidir}/tests/requirements/dj42_cms41.txt basepython = - py38: python3.8 py39: python3.9 py310: python3.10 From 0c85acf7d86935567e02f4117797b27468f464a0 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Mon, 26 Aug 2024 16:58:59 +0800 Subject: [PATCH 02/22] updates --- djangocms_navigation/admin.py | 16 ++++++++++++---- djangocms_navigation/compat.py | 3 +++ djangocms_navigation/utils.py | 22 ++++++++++++++++------ djangocms_navigation/views.py | 17 +++++++++++++---- tests/requirements/dj42_cms41.txt | 4 ++-- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index e6f6846be..50f4b2f40 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -35,6 +35,8 @@ from .utils import is_versioning_enabled, purge_menu_cache, reverse_admin_name from .views import ContentObjectSelect2View, MessageStorageView +from .compat import CMS_41 + try: from djangocms_version_locking.helpers import ( @@ -402,10 +404,16 @@ def _get_delete_link(self, obj, request, disabled=False): args=[request.menu_content_id, obj.id] ) - return render_to_string( - "djangocms_versioning/admin/discard_icon.html", - {"discard_url": delete_url, "disabled": disabled, "object_id": obj.id}, - ) + if CMS_41: + return render_to_string( + "djangocms_versioning/admin/icons/discard_icon.html", + {"url": delete_url, "disabled": disabled, "object_id": obj.id} + ) + else: + return render_to_string( + "djangocms_versioning/admin/discard_icon.html", + {"discard_url": delete_url, "disabled": disabled, "object_id": obj.id}, + ) def get_queryset(self, request): if hasattr(request, "menu_content_id"): diff --git a/djangocms_navigation/compat.py b/djangocms_navigation/compat.py index 3517f7d59..dd9bb89d5 100644 --- a/djangocms_navigation/compat.py +++ b/djangocms_navigation/compat.py @@ -1,5 +1,8 @@ from packaging.version import Version from treebeard import __version__ as treebeard_version +from cms import __version__ as CMS_VERSION + TREEBEARD_4_5 = Version(treebeard_version) < Version('4.6') +CMS_41 = Version("4.1") <= Version(CMS_VERSION) diff --git a/djangocms_navigation/utils.py b/djangocms_navigation/utils.py index 30064dc54..493c0f901 100644 --- a/djangocms_navigation/utils.py +++ b/djangocms_navigation/utils.py @@ -10,6 +10,8 @@ from djangocms_versioning.constants import DRAFT, PUBLISHED from djangocms_versioning.helpers import remove_published_where +from .compat import CMS_41 + def get_admin_name(model, name): name = '{}_{}_{}'.format( @@ -97,9 +99,17 @@ def get_latest_page_content_for_page_grouper(obj, language): :return: A queryset if an item exists, or None if not. :rtype: Queryset object, or None """ - page_contents = PageContent.objects.filter( - page=obj, - language=language, - versions__state__in=[DRAFT, PUBLISHED] - ).order_by("-versions__pk") - return remove_published_where(page_contents).first() + if CMS_41: + page_contents = PageContent.admin_manager.filter( + page=obj, + language=language, + versions__state__in=[DRAFT, PUBLISHED] + ).order_by("-versions__pk") + return page_contents.first() + else: + page_contents = PageContent.objects.filter( + page=obj, + language=language, + versions__state__in=[DRAFT, PUBLISHED] + ).order_by("-versions__pk") + return remove_published_where(page_contents).first() diff --git a/djangocms_navigation/views.py b/djangocms_navigation/views.py index bb49a4ff4..eee45cf3b 100644 --- a/djangocms_navigation/views.py +++ b/djangocms_navigation/views.py @@ -12,6 +12,8 @@ from djangocms_navigation.utils import is_model_supported, supported_models +from .compat import CMS_41 + class ContentObjectSelect2View(View): menu_content_model = None @@ -38,10 +40,17 @@ def get(self, request, *args, **kwargs): # Removing unpublished pages from queryset if model == Page: - queryset_data = [ - page for page in queryset_data - if not getattr(page.get_title_obj().versions.first(), "state", None) in [ARCHIVED, UNPUBLISHED] - ] + breakpoint() + if CMS_41: + queryset_data = [ + page for page in queryset_data + if getattr(page.get_content_obj().versions.first(), "state", None) not in [ARCHIVED, UNPUBLISHED] + ] + else: + queryset_data = [ + page for page in queryset_data + if getattr(page.get_title_obj().versions.first(), "state", None) not in [ARCHIVED, UNPUBLISHED] + ] data = { "results": [{"text": str(obj), "id": obj.pk} for obj in queryset_data] diff --git a/tests/requirements/dj42_cms41.txt b/tests/requirements/dj42_cms41.txt index 52dd24ec3..f22b3f3b5 100644 --- a/tests/requirements/dj42_cms41.txt +++ b/tests/requirements/dj42_cms41.txt @@ -16,6 +16,6 @@ djangocms-text-ckeditor==5.1.5 djangocms-versioning==2.0.2 https://github.com/FreemanPancake/djangocms-version-locking/tarball/feature/djangocms4x-compat#egg=djangocms-version-locking https://github.com/django-cms/djangocms-moderation/tarball/master#egg=djangocms-moderation -https://github.com/FidelityInternational/djangocms-references/tarball/release/1.5.0#egg=djangocms-references +https://github.com/FidelityInternational/djangocms-references/tarball/feat/cms41-compat#egg=djangocms-references https://github.com/django-cms/djangocms-alias/tarball/master#egg=djangocms-alias -https://github.com/joshyu/djangocms-snippet/tarball/master#egg=djangocms-snippet +https://github.com/django-cms/djangocms-snippet/tarball/master#egg=djangocms-snippet==5.0.0.a1 From b7b9074bafc6ad4daa7c57c11778f71385d9f7f1 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Fri, 25 Oct 2024 14:28:40 +0800 Subject: [PATCH 03/22] updates --- djangocms_navigation/views.py | 7 ++----- tests/test_admin.py | 14 +++++++++++--- tox.ini | 1 + 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/djangocms_navigation/views.py b/djangocms_navigation/views.py index eee45cf3b..b65b72e16 100644 --- a/djangocms_navigation/views.py +++ b/djangocms_navigation/views.py @@ -8,11 +8,9 @@ from cms.models import Page from cms.utils import get_current_site, get_language_from_request -from djangocms_versioning.constants import ARCHIVED, UNPUBLISHED - from djangocms_navigation.utils import is_model_supported, supported_models - -from .compat import CMS_41 +from djangocms_navigation.compat import CMS_41 +from djangocms_versioning.constants import ARCHIVED, UNPUBLISHED class ContentObjectSelect2View(View): @@ -40,7 +38,6 @@ def get(self, request, *args, **kwargs): # Removing unpublished pages from queryset if model == Page: - breakpoint() if CMS_41: queryset_data = [ page for page in queryset_data diff --git a/tests/test_admin.py b/tests/test_admin.py index 8a0466c40..1571166bd 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -2,9 +2,12 @@ import importlib import json import sys + +from bs4 import BeautifulSoup from unittest import skipIf, skipUnless from unittest.mock import patch + from django.contrib import admin from django.contrib.contenttypes.models import ContentType from django.contrib.messages import get_messages @@ -14,12 +17,11 @@ from django.test.utils import override_settings from django.utils.translation import gettext_lazy as _ -from cms.api import add_plugin, create_page, create_title +from cms.api import add_plugin, create_page from cms.test_utils.testcases import CMSTestCase from cms.toolbar.utils import get_object_preview_url from cms.utils.compat import DJANGO_4_1 -from bs4 import BeautifulSoup from djangocms_versioning.constants import DRAFT, PUBLISHED, UNPUBLISHED from djangocms_versioning.exceptions import ConditionFailed from djangocms_versioning.helpers import version_list_url @@ -34,8 +36,14 @@ from djangocms_navigation.models import Menu, MenuContent, MenuItem from djangocms_navigation.test_utils import factories +from djangocms_navigation.compat import CMS_41 from .utils import UsefulAssertsMixin, disable_versioning_for_navigation +if CMS_41: + from cms.api import create_page_content # noqa: F401 +else: + from cms.api import create_title as create_page_content # noqa: F401 + class MenuItemChangelistTestCase(CMSTestCase): def setUp(self): @@ -2137,7 +2145,7 @@ def test_menucontent_references_integration(self): in_navigation=True, **kwargs ) - page_content = create_title("en", "Draft Page", page, created_by=self.user) + page_content = create_page_content("en", "Draft Page", page, created_by=self.user) placeholder = factories.PlaceholderFactory( source=page_content, diff --git a/tox.ini b/tox.ini index ed7e66636..8aef5852f 100644 --- a/tox.ini +++ b/tox.ini @@ -7,6 +7,7 @@ envlist = skip_missing_interpreters=True [testenv] +allowlist_externals=coverage deps = flake8: -r{toxinidir}/tests/requirements/requirements_base.txt isort: -r{toxinidir}/tests/requirements/requirements_base.txt From f02ed8bd8d72d8298fcd77f692f20dceeff16ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Tue, 29 Oct 2024 11:27:57 +0800 Subject: [PATCH 04/22] fix menuitem changelist layout issue --- djangocms_navigation/admin.py | 44 ++++++++++++++++++++++++------- tests/requirements/dj42_cms41.txt | 2 +- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 50f4b2f40..082fd8a30 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -15,6 +15,7 @@ from django.template.response import TemplateResponse from django.urls import path, re_path, reverse, reverse_lazy from django.utils.html import format_html, format_html_join +from django.utils.safestring import mark_safe from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from django.views.i18n import JavaScriptCatalog @@ -26,6 +27,8 @@ from djangocms_versioning.models import Version from treebeard.admin import TreeAdmin +from cms.admin.utils import ChangeListActionsMixin + from .compat import TREEBEARD_4_5 from .conf import TREE_MAX_RESULT_PER_PAGE_COUNT from .filters import LanguageFilter @@ -39,10 +42,16 @@ try: - from djangocms_version_locking.helpers import ( - content_is_unlocked_for_user, - version_is_locked, - ) + if CMS_41: + from djangocms_versioning.helpers import ( + content_is_unlocked_for_user, + version_is_locked, + ) + else: + from djangocms_version_locking.helpers import ( + content_is_unlocked_for_user, + version_is_locked, + ) using_version_lock = True LOCK_MESSAGE = _( @@ -140,7 +149,10 @@ def get_list_display(self, request): def is_locked(self, obj): version = self.get_version(obj) if version.state == DRAFT and version_is_locked(version): - return render_to_string("djangocms_version_locking/admin/locked_icon.html") + if CMS_41: + return mark_safe('') + else: + return render_to_string("djangocms_version_locking/admin/locked_icon.html") return "" def _get_references_link(self, obj, request): @@ -264,7 +276,7 @@ def get_menuitem_link(self, obj): @admin.register(MenuItem) -class MenuItemAdmin(TreeAdmin): +class MenuItemAdmin(ChangeListActionsMixin, TreeAdmin): form = MenuItemForm menu_content_model = MenuContent menu_model = Menu @@ -391,6 +403,17 @@ def _get_edit_link(self, obj, request, disabled=False): args=[request.menu_content_id, obj.id] ) + if CMS_41: + return self.admin_action_button( + edit_url, + icon="pencil", + title=_("Edit"), + name="edit", + disabled=disabled, + action="post", + keepsideframe=False, + ) + return render_to_string( "djangocms_versioning/admin/icons/edit_icon.html", {"url": edit_url, "disabled": disabled, "object_id": obj.id} @@ -405,9 +428,12 @@ def _get_delete_link(self, obj, request, disabled=False): ) if CMS_41: - return render_to_string( - "djangocms_versioning/admin/icons/discard_icon.html", - {"url": delete_url, "disabled": disabled, "object_id": obj.id} + return self.admin_action_button( + delete_url, + icon="bin", + title=_("Discord"), + name="discard", + disabled=disabled, ) else: return render_to_string( diff --git a/tests/requirements/dj42_cms41.txt b/tests/requirements/dj42_cms41.txt index f22b3f3b5..36f544b8f 100644 --- a/tests/requirements/dj42_cms41.txt +++ b/tests/requirements/dj42_cms41.txt @@ -18,4 +18,4 @@ https://github.com/FreemanPancake/djangocms-version-locking/tarball/feature/djan https://github.com/django-cms/djangocms-moderation/tarball/master#egg=djangocms-moderation https://github.com/FidelityInternational/djangocms-references/tarball/feat/cms41-compat#egg=djangocms-references https://github.com/django-cms/djangocms-alias/tarball/master#egg=djangocms-alias -https://github.com/django-cms/djangocms-snippet/tarball/master#egg=djangocms-snippet==5.0.0.a1 +https://github.com/django-cms/djangocms-snippet/tarball/master#egg=djangocms-snippet \ No newline at end of file From 18f1099741573a97093fcf510b9123d780c8eb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Tue, 29 Oct 2024 13:51:50 +0800 Subject: [PATCH 05/22] change assertion from -versioning to standard. --- tests/test_admin.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index 1571166bd..12faa1d57 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -226,14 +226,14 @@ def test_list_display_without_version_locking(self): list_display[0:4], ["title", "get_author", "get_modified_date", "get_versioning_state"] ) - self.assertIn("cms-versioning-action-btn", list_display[-1]) + self.assertIn("cms-action-btn", list_display[-1]) # The preview button is present - self.assertIn("cms-versioning-action-preview", list_display[-1]) + self.assertIn("cms-action-preview", list_display[-1]) # The edit button is present - self.assertIn("cms-versioning-action-edit", list_display[-1]) + self.assertIn("cms-action-edit", list_display[-1]) self.assertIn("cms-form-get-method", list_display[-1]) - self.assertIn("js-versioning-action", list_display[-1]) - self.assertIn("js-versioning-keep-sideframe", list_display[-1]) + self.assertIn("js-action", list_display[-1]) + self.assertIn("js-keep-sideframe", list_display[-1]) @override_settings(DJANGOCMS_NAVIGATION_VERSIONING_ENABLED=False) @disable_versioning_for_navigation() @@ -1992,7 +1992,7 @@ def test_preview_link(self): func = self.modeladmin._list_actions(self.get_request("/admin")) response = func(menu_content) - self.assertIn("cms-versioning-action-preview", response) + self.assertIn("cms-action-preview", response) self.assertIn('title="Preview"', response) self.assertIn(preview_endpoint, response) @@ -2007,7 +2007,7 @@ def test_edit_link(self): edit_endpoint = reverse("admin:djangocms_versioning_menucontentversion_edit_redirect", args=(version.pk,),) response = func(menu_content) - self.assertIn("cms-versioning-action-btn", response) + self.assertIn("cms-action-btn", response) self.assertIn('title="Edit"', response) self.assertIn(edit_endpoint, response) @@ -2031,7 +2031,7 @@ def test_edit_link_not_shown(self): response = func(version.content) - self.assertNotIn("cms-versioning-action-edit ", response) + self.assertNotIn("cms-action-edit ", response) class MenuItemListActionsTestCase(CMSTestCase): @@ -2051,7 +2051,7 @@ def test_edit_link(self): ) response = func(menu_content.root) - self.assertIn("cms-versioning-action-btn", response) + self.assertIn("cms-action-btn", response) self.assertIn('title="Edit"', response) self.assertIn(edit_endpoint, response) @@ -2072,9 +2072,9 @@ def test_menucontent_changelist_url_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menucontent_modeladmin._get_edit_link(menucontent, request) - # The url link should keep the sideframe open - self.assertIn("js-versioning-keep-sideframe", url_markup) - self.assertNotIn("js-versioning-close-sideframe", url_markup) + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) def test_menucontent_preview_link_opens_in_sideframe(self): """ @@ -2087,9 +2087,9 @@ def test_menucontent_preview_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menucontent_modeladmin._get_preview_link(menucontent, request) - # The url link should keep the sideframe open - self.assertIn("js-versioning-keep-sideframe", url_markup) - self.assertNotIn("js-versioning-close-sideframe", url_markup) + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) def test_menuitem_changelist_edit_url_link_opens_in_sideframe(self): """ @@ -2104,9 +2104,9 @@ def test_menuitem_changelist_edit_url_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menuitem_modeladmin._get_edit_link(child, request) - # The url link should keep the sideframe open - self.assertIn("js-versioning-keep-sideframe", url_markup) - self.assertNotIn("js-versioning-close-sideframe", url_markup) + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) def test_menuitem_changelist_delete_url_link_opens_in_sideframe(self): """ @@ -2121,9 +2121,9 @@ def test_menuitem_changelist_delete_url_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menuitem_modeladmin._get_delete_link(child, request) - # The url link should keep the sideframe open - self.assertIn("js-versioning-keep-sideframe", url_markup) - self.assertNotIn("js-versioning-close-sideframe", url_markup) + # The url link should keep the sideframe close + self.assertIn("js-keep-sideframe", url_markup) + self.assertNotIn("js-close-sideframe", url_markup) class ReferencesIntegrationTestCase(CMSTestCase): From 376b457046d3092ba9392305cbc09ab2abc06c34 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Tue, 29 Oct 2024 13:57:55 +0800 Subject: [PATCH 06/22] fix: test --- tests/test_views.py | 40 ++++++++++++++++++++++------------------ tox.ini | 6 +++--- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tests/test_views.py b/tests/test_views.py index f2fbf4611..e7e2a802b 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -127,11 +127,11 @@ def test_raise_error_when_return_unregistered_user_model_in_select2_view(self): def test_select2_view_text_page_repr(self): """Result should contain model repr text""" page_contenttype_id = ContentType.objects.get_for_model(Page).id - PageContentFactory( - title="test", menu_title="test", page_title="test", language="en" + PageContentWithVersionFactory( + title="test", menu_title="test", page_title="test", language="en", version__state=PUBLISHED ) # flake8: noqa - PageContentFactory( - title="test2", menu_title="test2", page_title="test2", language="en" + PageContentWithVersionFactory( + title="test2", menu_title="test2", page_title="test2", language="en", version__state=PUBLISHED ) # flake8: noqa with self.login_user_context(self.superuser): response = self.client.get( @@ -145,11 +145,11 @@ def test_select2_view_text_page_repr(self): def test_select2_view_search_text_page(self): """ Both pages should appear in results for test query""" page_contenttype_id = ContentType.objects.get_for_model(Page).id - PageContentFactory( - title="test", menu_title="test", page_title="test", language="en" + PageContentWithVersionFactory( + title="test", menu_title="test", page_title="test", language="en", version__state=PUBLISHED ) - PageContentFactory( - title="test2", menu_title="test2", page_title="test2", language="en" + PageContentWithVersionFactory( + title="test2", menu_title="test2", page_title="test2", language="en", version__state=PUBLISHED ) with self.login_user_context(self.superuser): response = self.client.get( @@ -163,11 +163,11 @@ def test_select2_view_search_text_page(self): def test_select2_view_search_exact_text_page(self): """ One page should appear in results for test2 exact query""" page_contenttype_id = ContentType.objects.get_for_model(Page).id - PageContentFactory( - title="test", menu_title="test", page_title="test", language="en" + PageContentWithVersionFactory( + title="test", menu_title="test", page_title="test", language="en", version__state=PUBLISHED ) - PageContentFactory( - title="test2", menu_title="test2", page_title="test2", language="en" + PageContentWithVersionFactory( + title="test2", menu_title="test2", page_title="test2", language="en", version__state=PUBLISHED ) with self.login_user_context(self.superuser): response = self.client.get( @@ -272,8 +272,8 @@ def test_with_pages_in_multiple_languages(self): Check that when page content exists in multiple languages, only pages for the current language are returned """ page_contenttype_id = ContentType.objects.get_for_model(Page).id - french = PageContentFactory( - title="test", menu_title="test", page_title="test", language="fr", + french = PageContentWithVersionFactory( + title="test", menu_title="test", page_title="test", language="fr", version__state=PUBLISHED ) PageContentFactory.create_batch(10, title="test", menu_title="test", page_title="test", language="en") @@ -300,7 +300,7 @@ def test_with_pages_for_multiple_sites(self): site1 = Site.objects.create(name="site1.com", domain="site1.com") site2 = Site.objects.create(name="site2.com", domain="site2.com") PageContentFactory.create_batch(10, title="test", page__node__site=site1, language="en") - expected = PageContentFactory(title="test", menu_title="site2 page", page__node__site=site2, language="en") + expected = PageContentWithVersionFactory(title="test", menu_title="site2 page", page__node__site=site2, language="en", version__state=PUBLISHED) with self.login_user_context(self.superuser): response = self.client.get( @@ -322,7 +322,9 @@ def test_searching_for_page_slug(self): """ page_contenttype_id = ContentType.objects.get_for_model(Page).id PageContentFactory.create_batch(10, language="en") - expected = PageContentFactory(title="Test search by slug", menu_title="Test search by slug", language="en") + expected = PageContentWithVersionFactory( + title="Test search by slug", menu_title="Test search by slug", language="en", version__state=PUBLISHED + ) slug = expected.page.get_slug("en") # early smoke test to stop us getting a false positive by finding the page by its title rather than slug self.assertNotEqual(expected.title.lower(), slug) @@ -347,7 +349,9 @@ def test_searching_for_page_path(self): """ page_contenttype_id = ContentType.objects.get_for_model(Page).id PageContentFactory.create_batch(10, language="en") - expected = PageContentFactory(menu_title="Test search by overwritten url", language="en") + expected = PageContentWithVersionFactory( + title="test", menu_title="Test search by overwritten url", page_title="test", language="en", version__state=PUBLISHED + ) # update page urls to use a randomly generated path to represent setting an overwritten url path = fake.uri_path() expected.page.urls.update(path=path) @@ -480,7 +484,7 @@ def test_page_queryset_filters_pages_by_current_language(self): for language in ["en", "fr", "de", "it"]: with self.subTest(msg=language): request = self.get_request(language=language) - request.GET = {"content_type_id": self.page_contenttype_id, "query": "test"} + request.GET = {"content_type_id": self.page_contenttype_id, "query": "test", "language": language} self.view.request = request results = self.view.get_data() diff --git a/tox.ini b/tox.ini index 8aef5852f..7394d0349 100644 --- a/tox.ini +++ b/tox.ini @@ -12,9 +12,9 @@ deps = flake8: -r{toxinidir}/tests/requirements/requirements_base.txt isort: -r{toxinidir}/tests/requirements/requirements_base.txt - dj32_cms40: -r{toxinidir}/tests/requirements/dj32_cms40.txt - dj42_cms40: -r{toxinidir}/tests/requirements/dj42_cms40.txt - dj42_cms41: -r{toxinidir}/tests/requirements/dj42_cms41.txt + dj32-cms40: -r{toxinidir}/tests/requirements/dj32_cms40.txt + dj42-cms40: -r{toxinidir}/tests/requirements/dj42_cms40.txt + dj42-cms41: -r{toxinidir}/tests/requirements/dj42_cms41.txt basepython = py39: python3.9 From 31577f92916f42918d8cbf0db33dcce64d1e2649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Tue, 29 Oct 2024 14:48:34 +0800 Subject: [PATCH 07/22] change menuitem inherit class. --- djangocms_navigation/admin.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 082fd8a30..8471dcf43 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -27,8 +27,6 @@ from djangocms_versioning.models import Version from treebeard.admin import TreeAdmin -from cms.admin.utils import ChangeListActionsMixin - from .compat import TREEBEARD_4_5 from .conf import TREE_MAX_RESULT_PER_PAGE_COUNT from .filters import LanguageFilter @@ -41,12 +39,16 @@ from .compat import CMS_41 +menuitem_admin_class = [TreeAdmin] + try: if CMS_41: + from cms.admin.utils import ChangeListActionsMixin from djangocms_versioning.helpers import ( content_is_unlocked_for_user, version_is_locked, ) + menuitem_admin_class.insert(0, ChangeListActionsMixin) else: from djangocms_version_locking.helpers import ( content_is_unlocked_for_user, @@ -55,8 +57,7 @@ using_version_lock = True LOCK_MESSAGE = _( - "The item is currently locked or you don't " - "have permission to change it" + "The item is currently locked or you don't have permission to change it" ) except ImportError: using_version_lock = False @@ -276,7 +277,7 @@ def get_menuitem_link(self, obj): @admin.register(MenuItem) -class MenuItemAdmin(ChangeListActionsMixin, TreeAdmin): +class MenuItemAdmin(*menuitem_admin_class): form = MenuItemForm menu_content_model = MenuContent menu_model = Menu From ed2237aa15a0630672c89d61514dfdd592232ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Tue, 29 Oct 2024 16:17:55 +0800 Subject: [PATCH 08/22] fix text error for MenuItemAdminVersionLocked, because locked_by is not passed through. --- tests/test_admin.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index 12faa1d57..084a4281f 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -376,7 +376,15 @@ def test_get_changelist_template_preview(self): class MenuItemAdminVersionLocked(CMSTestCase, UsefulAssertsMixin): def setUp(self): - self.menu_content = factories.MenuContentWithVersionFactory(version__state=DRAFT) + self.author_user = factories.UserFactory(is_staff=True) + menu_edit_creation_param = { + "version__state": DRAFT, + } + if CMS_41: + menu_edit_creation_param.update({ + "version__locked_by": self.author_user, + }) + self.menu_content = factories.MenuContentWithVersionFactory(**menu_edit_creation_param) self.item = factories.ChildMenuItemFactory(parent=self.menu_content.root) self.change_url = reverse( @@ -386,7 +394,12 @@ def setUp(self): self.client.force_login(self.get_superuser()) # moving a node - menu_content = factories.MenuContentWithVersionFactory() + menu_move_creation_param = {} + if CMS_41: + menu_move_creation_param.update({ + "version__locked_by": self.author_user, + }) + menu_content = factories.MenuContentWithVersionFactory(**menu_move_creation_param) self.child = factories.ChildMenuItemFactory(parent=menu_content.root) self.child_of_child = factories.ChildMenuItemFactory(parent=self.child) self.move_url = reverse( From df7eeb239ee84eb8170a135b6b9b593eeb6ea39a Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Tue, 29 Oct 2024 16:30:20 +0800 Subject: [PATCH 09/22] fix: test_cms_menus --- djangocms_navigation/test_utils/factories.py | 6 +++ tests/test_cms_menus.py | 39 ++++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/djangocms_navigation/test_utils/factories.py b/djangocms_navigation/test_utils/factories.py index a96bed0c6..9f0428b3e 100644 --- a/djangocms_navigation/test_utils/factories.py +++ b/djangocms_navigation/test_utils/factories.py @@ -12,6 +12,7 @@ from djangocms_versioning.models import Version from factory.fuzzy import FuzzyChoice, FuzzyInteger, FuzzyText +from ..compat import CMS_41 from ..models import Menu, MenuContent, MenuItem @@ -125,9 +126,14 @@ class PageContentWithVersionFactory(PageContentFactory): def version(self, create, extracted, **kwargs): # NOTE: Use this method as below to define version attributes: # PageContentWithVersionFactory(version__label='label1') + if not create: # Simple build, do nothing. return + + if not CMS_41 and 'locked_by' in kwargs: + kwargs.pop('locked_by') + PageVersionFactory(content=self, **kwargs) diff --git a/tests/test_cms_menus.py b/tests/test_cms_menus.py index d84ace4b0..bf1181175 100644 --- a/tests/test_cms_menus.py +++ b/tests/test_cms_menus.py @@ -327,12 +327,14 @@ def test_draft_menu_on_draft_page(self): page=page, language=self.language, version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), version__state=PUBLISHED, ) pagecontent_draft = factories.PageContentWithVersionFactory( page=page, language=self.language, version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), version__state=DRAFT, ) draft_child = factories.ChildMenuItemFactory(parent=menu_cont_draft.root, content=pagecontent_draft.page) @@ -373,12 +375,14 @@ def test_draft_menu_on_published_page(self): page=page, language=self.language, version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), version__state=PUBLISHED, ) pagecontent_draft = factories.PageContentWithVersionFactory( page=page, language=self.language, version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), version__state=DRAFT, ) @@ -393,8 +397,7 @@ def test_draft_menu_on_published_page(self): # Node added in draft menu version is not rendered in published view, only published menu nodes are rendered with self.login_user_context(self.get_superuser()): - response = self.client.get(pagecontent_published.page.get_absolute_url()) - + response = self.client.get(pagecontent_draft.page.get_absolute_url()) self.assertEqual(response.status_code, 200) self.assertIn(published_child.title, str(response.content)) self.assertNotIn(draft_child.title, str(response.content)) @@ -451,13 +454,20 @@ def setUp(self): self.language = "en" # A page that will contain a menu i.e. we can see the menu rendered on this page preview_pagecontent = factories.PageContentWithVersionFactory( + language=self.language, + version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), + version__state=DRAFT, + ) + published_pagecontent = factories.PageContentWithVersionFactory( language=self.language, version__created_by=self.get_superuser(), version__state=PUBLISHED, ) + self.edit_endpoint = get_object_edit_url(preview_pagecontent, language=self.language) self.preview_endpoint = get_object_preview_url(preview_pagecontent, language=self.language) - self.live_endpoint = preview_pagecontent.get_absolute_url(language=self.language) + self.live_endpoint = published_pagecontent.get_absolute_url(language=self.language) # Menu creation self.menu = factories.MenuFactory() self.published_menu_content = factories.MenuContentWithVersionFactory( @@ -1678,14 +1688,21 @@ class MainNavigationIntegrationTestCase(CMSTestCase): """ def setUp(self): # create a page and urls we can use to make a request with the test client + self.draft_pagecontent = factories.PageContentWithVersionFactory( + language="en", + version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), + version__state=DRAFT, + ) + self.pagecontent = factories.PageContentWithVersionFactory( language="en", version__created_by=self.get_superuser(), version__state=PUBLISHED, ) self.live_url = self.pagecontent.get_absolute_url() - self.edit_url = get_object_edit_url(self.pagecontent, language="en") - self.preview_url = get_object_preview_url(self.pagecontent, language="en") + self.edit_url = get_object_edit_url(self.draft_pagecontent, language="en") + self.preview_url = get_object_preview_url(self.draft_pagecontent, language="en") # create two menus, neither marked as the main navigation self.first_menucontent = factories.MenuContentWithVersionFactory( language="en", @@ -1753,7 +1770,6 @@ def test_both_main_navigation(self): edit_response = self.client.get(self.edit_url) preview_response = self.client.get(self.preview_url) live_response = self.client.get(self.live_url) - for response in [edit_response, preview_response, live_response]: with self.subTest(response): nav_tree = get_nav_from_response(response) @@ -1791,6 +1807,13 @@ def test_both_main_navigation_multiple_sites(self): version__state=PUBLISHED, page__node__site=site_2, ) + site_2_draft_pagecontent = factories.PageContentWithVersionFactory( + language="en", + version__created_by=self.get_superuser(), + version__locked_by=self.get_superuser(), + version__state=DRAFT, + page__node__site=site_2, + ) # test for when the menu is marked main navigation, and when it isnt for is_main_navigation in [False, True]: @@ -1800,8 +1823,8 @@ def test_both_main_navigation_multiple_sites(self): make_main_navigation(site_2_menucontent) with self.login_user_context(self.get_superuser()): - edit_response = self.client.get(get_object_edit_url(site_2_pagecontent)) - preview_response = self.client.get(get_object_preview_url(site_2_pagecontent)) + edit_response = self.client.get(get_object_edit_url(site_2_draft_pagecontent)) + preview_response = self.client.get(get_object_preview_url(site_2_draft_pagecontent)) live_response = self.client.get(site_2_pagecontent.get_absolute_url()) for response in [edit_response, preview_response, live_response]: From 246b580a1ac874a6423959efbcedb8b30855497e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Tue, 29 Oct 2024 16:31:15 +0800 Subject: [PATCH 10/22] fix edit url got redirect issue for test_utils. --- tests/test_utils.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index a1c2ab234..0e89b0c48 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -15,6 +15,7 @@ UNPUBLISHED, ) +from djangocms_navigation.compat import CMS_41 from djangocms_navigation.models import MenuContent from djangocms_navigation.test_utils import factories from djangocms_navigation.test_utils.app_1.models import TestModel1, TestModel2 @@ -108,6 +109,12 @@ def setUp(self): version__state=PUBLISHED, ) + # for draft version get edit url. + self.page_content_draft = factories.PageContentWithVersionFactory( + version__created_by=self.get_superuser(), + version__state=DRAFT, + ) + def test_live_endpoint(self): live_endpoint = self.page_content.get_absolute_url(language=self.page_content.language) @@ -128,7 +135,7 @@ def test_preview_endpoint(self): self.assertTrue(actual) def test_edit_endpoint(self): - edit_endpoint = get_object_edit_url(self.page_content, language=self.page_content.language) + edit_endpoint = get_object_edit_url(self.page_content_draft, language=self.page_content.language) with self.login_user_context(self.get_superuser()): response = self.client.get(edit_endpoint) From 1858a8f0cc6e005760fc3c125219233ca0109bd4 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Tue, 29 Oct 2024 18:43:46 +0800 Subject: [PATCH 11/22] fix: test_cms_menus --- djangocms_navigation/admin.py | 3 ++- tests/test_cms_menus.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 8471dcf43..3c30030db 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -57,7 +57,8 @@ using_version_lock = True LOCK_MESSAGE = _( - "The item is currently locked or you don't have permission to change it" + "The item is currently locked or you don't " + "have permission to change it" ) except ImportError: using_version_lock = False diff --git a/tests/test_cms_menus.py b/tests/test_cms_menus.py index bf1181175..8d114d5c4 100644 --- a/tests/test_cms_menus.py +++ b/tests/test_cms_menus.py @@ -1546,6 +1546,7 @@ def test_menu_with_multiple_languages(self): 'request': self.get_request( root_pagecontent_it.page.get_absolute_url(language="it"), language="it", page=root_pagecontent_it.page) } + context_it_raw['request'].GET = {'language': 'it'} context_it = Context(context_it_raw) context_it = add_toolbar_to_request(context_it, root_pagecontent_it, view_mode="edit") template.render(context_it) From 91639951e414c1ba00fb76b8b6f247d997efd5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Wed, 30 Oct 2024 09:28:46 +0800 Subject: [PATCH 12/22] add logic for both cms < 4.1 and cms > 4.1 in test_admin --- tests/test_admin.py | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index 084a4281f..d8367be44 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -2085,9 +2085,14 @@ def test_menucontent_changelist_url_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menucontent_modeladmin._get_edit_link(menucontent, request) - # The url link should keep the sideframe close - self.assertNotIn("js-keep-sideframe", url_markup) - self.assertIn("js-close-sideframe", url_markup) + if CMS_41: + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) + else: + # The url link should keep the sideframe open + self.assertIn("js-versioning-keep-sideframe", url_markup) + self.assertNotIn("js-versioning-close-sideframe", url_markup) def test_menucontent_preview_link_opens_in_sideframe(self): """ @@ -2100,9 +2105,14 @@ def test_menucontent_preview_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menucontent_modeladmin._get_preview_link(menucontent, request) - # The url link should keep the sideframe close - self.assertNotIn("js-keep-sideframe", url_markup) - self.assertIn("js-close-sideframe", url_markup) + if CMS_41: + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) + else: + # The url link should keep the sideframe open + self.assertIn("js-versioning-keep-sideframe", url_markup) + self.assertNotIn("js-versioning-close-sideframe", url_markup) def test_menuitem_changelist_edit_url_link_opens_in_sideframe(self): """ @@ -2117,9 +2127,14 @@ def test_menuitem_changelist_edit_url_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menuitem_modeladmin._get_edit_link(child, request) - # The url link should keep the sideframe close - self.assertNotIn("js-keep-sideframe", url_markup) - self.assertIn("js-close-sideframe", url_markup) + if CMS_41: + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) + else: + # The url link should keep the sideframe open + self.assertIn("js-versioning-keep-sideframe", url_markup) + self.assertNotIn("js-versioning-close-sideframe", url_markup) def test_menuitem_changelist_delete_url_link_opens_in_sideframe(self): """ @@ -2134,9 +2149,14 @@ def test_menuitem_changelist_delete_url_link_opens_in_sideframe(self): request.menu_content_id = menucontent.pk url_markup = self.menuitem_modeladmin._get_delete_link(child, request) - # The url link should keep the sideframe close - self.assertIn("js-keep-sideframe", url_markup) - self.assertNotIn("js-close-sideframe", url_markup) + if CMS_41: + # The url link should keep the sideframe close + self.assertNotIn("js-keep-sideframe", url_markup) + self.assertIn("js-close-sideframe", url_markup) + else: + # The url link should keep the sideframe open + self.assertIn("js-versioning-keep-sideframe", url_markup) + self.assertNotIn("js-versioning-close-sideframe", url_markup) class ReferencesIntegrationTestCase(CMSTestCase): From d8768d9d6c301a1c2913d736779d79e96e5c2966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Wed, 30 Oct 2024 09:43:28 +0800 Subject: [PATCH 13/22] add logic for both cms < 4.1 and cms > 4.1 in test_admin. delete url --- tests/test_admin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index d8367be44..c90133d9f 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -2150,9 +2150,9 @@ def test_menuitem_changelist_delete_url_link_opens_in_sideframe(self): url_markup = self.menuitem_modeladmin._get_delete_link(child, request) if CMS_41: - # The url link should keep the sideframe close - self.assertNotIn("js-keep-sideframe", url_markup) - self.assertIn("js-close-sideframe", url_markup) + # The url link should keep the sideframe open by default + self.assertIn("js-keep-sideframe", url_markup) + self.assertNotIn("js-close-sideframe", url_markup) else: # The url link should keep the sideframe open self.assertIn("js-versioning-keep-sideframe", url_markup) From 0d37570e243f16c5a8756837a5d35444a4fe04d9 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Wed, 30 Oct 2024 10:26:10 +0800 Subject: [PATCH 14/22] fix: test_admin --- tests/test_admin.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index c90133d9f..9ae803dcb 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -9,6 +9,7 @@ from django.contrib import admin +from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from django.contrib.messages import get_messages from django.contrib.sites.models import Site @@ -1377,6 +1378,16 @@ def test_menuitem_delete_view_item_with_children(self): content ) + def get_permission(self, codename): + _list = codename.split('.') + app_label = '' + if len(_list) > 1: + app_label = _list[0] + codename = _list[1] + return Permission.objects.get(codename=codename, content_type__app_label=app_label) + else: + return Permission.objects.get(codename=codename) + def test_menuitem_delete_view_with_permission(self): """ With appropriate permissions, the delete view allows deletion of Menuitems @@ -1385,14 +1396,17 @@ def test_menuitem_delete_view_with_permission(self): "user_with_delete", is_staff=True ) menu_content = factories.MenuContentWithVersionFactory(version__created_by=user_with_delete_permissions) - child = factories.ChildMenuItemFactory(parent=menu_content.root) - new_child = factories.ChildMenuItemFactory(parent=menu_content.root) - child_of_child = factories.ChildMenuItemFactory(parent=child) - factories.ChildMenuItemFactory(parent=child_of_child) + child = factories.ChildMenuItemFactory(title="child", parent=menu_content.root) + new_child = factories.ChildMenuItemFactory(title="new_child", parent=menu_content.root) + child_of_child = factories.ChildMenuItemFactory(title="child_of_child", parent=child) + factories.ChildMenuItemFactory(title="child_of_child_2", parent=child_of_child) self.add_permission(user_with_delete_permissions, "view_menucontentversion") self.add_permission(user_with_delete_permissions, "delete_menuitem") + if CMS_41: + self.add_permission(user_with_delete_permissions, "djangocms_versioning.delete_versionlock") + # Delete one, editable node, with no children delete_url_single = reverse( "admin:djangocms_navigation_menuitem_delete", args=(menu_content.id, new_child.id,) From 5e14400768af12025083cde2b950709ca1d004c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Wed, 30 Oct 2024 10:43:17 +0800 Subject: [PATCH 15/22] fix assert error for cms 4.0 --- tests/test_admin.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/test_admin.py b/tests/test_admin.py index 9ae803dcb..bc4be2241 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -40,10 +40,12 @@ from djangocms_navigation.compat import CMS_41 from .utils import UsefulAssertsMixin, disable_versioning_for_navigation +versioning_substr = "" if CMS_41: from cms.api import create_page_content # noqa: F401 else: from cms.api import create_title as create_page_content # noqa: F401 + versioning_substr = "-versioning" class MenuItemChangelistTestCase(CMSTestCase): @@ -227,14 +229,15 @@ def test_list_display_without_version_locking(self): list_display[0:4], ["title", "get_author", "get_modified_date", "get_versioning_state"] ) - self.assertIn("cms-action-btn", list_display[-1]) + + self.assertIn(f"cms{versioning_substr}-action-btn", list_display[-1]) # The preview button is present - self.assertIn("cms-action-preview", list_display[-1]) + self.assertIn(f"cms{versioning_substr}-action-preview", list_display[-1]) # The edit button is present - self.assertIn("cms-action-edit", list_display[-1]) + self.assertIn(f"cms{versioning_substr}-action-edit", list_display[-1]) self.assertIn("cms-form-get-method", list_display[-1]) - self.assertIn("js-action", list_display[-1]) - self.assertIn("js-keep-sideframe", list_display[-1]) + self.assertIn(f"js{versioning_substr}-action", list_display[-1]) + self.assertIn(f"js{versioning_substr}-keep-sideframe", list_display[-1]) @override_settings(DJANGOCMS_NAVIGATION_VERSIONING_ENABLED=False) @disable_versioning_for_navigation() @@ -2019,7 +2022,7 @@ def test_preview_link(self): func = self.modeladmin._list_actions(self.get_request("/admin")) response = func(menu_content) - self.assertIn("cms-action-preview", response) + self.assertIn(f"cms{versioning_substr}-action-preview", response) self.assertIn('title="Preview"', response) self.assertIn(preview_endpoint, response) @@ -2034,7 +2037,7 @@ def test_edit_link(self): edit_endpoint = reverse("admin:djangocms_versioning_menucontentversion_edit_redirect", args=(version.pk,),) response = func(menu_content) - self.assertIn("cms-action-btn", response) + self.assertIn(f"cms{versioning_substr}-action-btn", response) self.assertIn('title="Edit"', response) self.assertIn(edit_endpoint, response) @@ -2078,7 +2081,7 @@ def test_edit_link(self): ) response = func(menu_content.root) - self.assertIn("cms-action-btn", response) + self.assertIn(f"cms{versioning_substr}-action-btn", response) self.assertIn('title="Edit"', response) self.assertIn(edit_endpoint, response) From f484d7fa346f682a53d8fcc46350a462e8da3424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Wed, 30 Oct 2024 11:17:06 +0800 Subject: [PATCH 16/22] fix import sort issue. --- djangocms_navigation/admin.py | 5 ++--- djangocms_navigation/compat.py | 4 ++-- djangocms_navigation/test_utils/factories.py | 2 +- djangocms_navigation/utils.py | 2 +- djangocms_navigation/views.py | 5 +++-- tests/test_admin.py | 8 +++----- tests/test_utils.py | 1 - tests/test_views.py | 14 ++++++++++++-- 8 files changed, 24 insertions(+), 17 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 3c30030db..1a0cc4171 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -27,7 +27,7 @@ from djangocms_versioning.models import Version from treebeard.admin import TreeAdmin -from .compat import TREEBEARD_4_5 +from .compat import CMS_41, TREEBEARD_4_5 from .conf import TREE_MAX_RESULT_PER_PAGE_COUNT from .filters import LanguageFilter from .forms import MenuContentForm, MenuItemForm @@ -36,14 +36,13 @@ from .utils import is_versioning_enabled, purge_menu_cache, reverse_admin_name from .views import ContentObjectSelect2View, MessageStorageView -from .compat import CMS_41 - menuitem_admin_class = [TreeAdmin] try: if CMS_41: from cms.admin.utils import ChangeListActionsMixin + from djangocms_versioning.helpers import ( content_is_unlocked_for_user, version_is_locked, diff --git a/djangocms_navigation/compat.py b/djangocms_navigation/compat.py index dd9bb89d5..2711c8d79 100644 --- a/djangocms_navigation/compat.py +++ b/djangocms_navigation/compat.py @@ -1,8 +1,8 @@ +from cms import __version__ as CMS_VERSION + from packaging.version import Version from treebeard import __version__ as treebeard_version -from cms import __version__ as CMS_VERSION - TREEBEARD_4_5 = Version(treebeard_version) < Version('4.6') CMS_41 = Version("4.1") <= Version(CMS_VERSION) diff --git a/djangocms_navigation/test_utils/factories.py b/djangocms_navigation/test_utils/factories.py index 9f0428b3e..fc644f1d4 100644 --- a/djangocms_navigation/test_utils/factories.py +++ b/djangocms_navigation/test_utils/factories.py @@ -126,7 +126,7 @@ class PageContentWithVersionFactory(PageContentFactory): def version(self, create, extracted, **kwargs): # NOTE: Use this method as below to define version attributes: # PageContentWithVersionFactory(version__label='label1') - + if not create: # Simple build, do nothing. return diff --git a/djangocms_navigation/utils.py b/djangocms_navigation/utils.py index 493c0f901..bfb168d21 100644 --- a/djangocms_navigation/utils.py +++ b/djangocms_navigation/utils.py @@ -99,7 +99,7 @@ def get_latest_page_content_for_page_grouper(obj, language): :return: A queryset if an item exists, or None if not. :rtype: Queryset object, or None """ - if CMS_41: + if CMS_41: page_contents = PageContent.admin_manager.filter( page=obj, language=language, diff --git a/djangocms_navigation/views.py b/djangocms_navigation/views.py index b65b72e16..acf5e5b6f 100644 --- a/djangocms_navigation/views.py +++ b/djangocms_navigation/views.py @@ -8,10 +8,11 @@ from cms.models import Page from cms.utils import get_current_site, get_language_from_request -from djangocms_navigation.utils import is_model_supported, supported_models -from djangocms_navigation.compat import CMS_41 from djangocms_versioning.constants import ARCHIVED, UNPUBLISHED +from djangocms_navigation.compat import CMS_41 +from djangocms_navigation.utils import is_model_supported, supported_models + class ContentObjectSelect2View(View): menu_content_model = None diff --git a/tests/test_admin.py b/tests/test_admin.py index bc4be2241..b1a7d557e 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -2,12 +2,9 @@ import importlib import json import sys - -from bs4 import BeautifulSoup from unittest import skipIf, skipUnless from unittest.mock import patch - from django.contrib import admin from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType @@ -23,6 +20,7 @@ from cms.toolbar.utils import get_object_preview_url from cms.utils.compat import DJANGO_4_1 +from bs4 import BeautifulSoup from djangocms_versioning.constants import DRAFT, PUBLISHED, UNPUBLISHED from djangocms_versioning.exceptions import ConditionFailed from djangocms_versioning.helpers import version_list_url @@ -33,13 +31,13 @@ MenuItemAdmin, MenuItemChangeList, ) -from djangocms_navigation.compat import TREEBEARD_4_5 +from djangocms_navigation.compat import CMS_41, TREEBEARD_4_5 from djangocms_navigation.models import Menu, MenuContent, MenuItem from djangocms_navigation.test_utils import factories -from djangocms_navigation.compat import CMS_41 from .utils import UsefulAssertsMixin, disable_versioning_for_navigation + versioning_substr = "" if CMS_41: from cms.api import create_page_content # noqa: F401 diff --git a/tests/test_utils.py b/tests/test_utils.py index 0e89b0c48..990205e43 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -15,7 +15,6 @@ UNPUBLISHED, ) -from djangocms_navigation.compat import CMS_41 from djangocms_navigation.models import MenuContent from djangocms_navigation.test_utils import factories from djangocms_navigation.test_utils.app_1.models import TestModel1, TestModel2 diff --git a/tests/test_views.py b/tests/test_views.py index e7e2a802b..83151d7e7 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -300,7 +300,13 @@ def test_with_pages_for_multiple_sites(self): site1 = Site.objects.create(name="site1.com", domain="site1.com") site2 = Site.objects.create(name="site2.com", domain="site2.com") PageContentFactory.create_batch(10, title="test", page__node__site=site1, language="en") - expected = PageContentWithVersionFactory(title="test", menu_title="site2 page", page__node__site=site2, language="en", version__state=PUBLISHED) + expected = PageContentWithVersionFactory( + title="test", + menu_title="site2 page", + page__node__site=site2, + language="en", + version__state=PUBLISHED + ) with self.login_user_context(self.superuser): response = self.client.get( @@ -350,7 +356,11 @@ def test_searching_for_page_path(self): page_contenttype_id = ContentType.objects.get_for_model(Page).id PageContentFactory.create_batch(10, language="en") expected = PageContentWithVersionFactory( - title="test", menu_title="Test search by overwritten url", page_title="test", language="en", version__state=PUBLISHED + title="test", + menu_title="Test search by overwritten url", + page_title="test", + language="en", + version__state=PUBLISHED ) # update page urls to use a randomly generated path to represent setting an overwritten url path = fake.uri_path() From 4b61fda20bc66fe15428d6e918bb6647efd54930 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Wed, 30 Oct 2024 11:20:01 +0800 Subject: [PATCH 17/22] fix: test_helpers --- tests/test_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index d340a718e..7a6911dff 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -160,7 +160,7 @@ def test_select_node_from_deeply_nested_nodes(self): factories.ChildMenuItemFactory(parent=menuversions.content.root) child3 = factories.ChildMenuItemFactory(parent=menuversions.content.root) factories.ChildMenuItemFactory(parent=child3) - max_queries = 52 + max_queries = 58 page_url = page_content.page.get_absolute_url() with self.assertNumQueries(FuzzyInt(3, max_queries)): From 22f270657b13a1ebe5055e469b1d32abfa9e0b77 Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Thu, 31 Oct 2024 14:32:56 +0800 Subject: [PATCH 18/22] chore: update djangocms-versioning to 2.1.0 in `dj42_cms41` --- tests/requirements/dj42_cms41.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements/dj42_cms41.txt b/tests/requirements/dj42_cms41.txt index 36f544b8f..1a27c0a13 100644 --- a/tests/requirements/dj42_cms41.txt +++ b/tests/requirements/dj42_cms41.txt @@ -13,7 +13,7 @@ django>=4.2,<5.0 django-treebeard>=4.6.0 django-cms>=4.1.0 djangocms-text-ckeditor==5.1.5 -djangocms-versioning==2.0.2 +djangocms-versioning==2.1.0 https://github.com/FreemanPancake/djangocms-version-locking/tarball/feature/djangocms4x-compat#egg=djangocms-version-locking https://github.com/django-cms/djangocms-moderation/tarball/master#egg=djangocms-moderation https://github.com/FidelityInternational/djangocms-references/tarball/feat/cms41-compat#egg=djangocms-references From 709b31684eaa4f2e3a053ee204e109be5390b5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Mon, 4 Nov 2024 16:14:50 +0800 Subject: [PATCH 19/22] change main nav link style to cms41. --- djangocms_navigation/admin.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 1a0cc4171..8618012ae 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -200,6 +200,15 @@ def _get_main_navigation_link(self, obj, request, disabled=False): if obj.menu.main_navigation: disabled = True + if CMS_41: + return self.admin_action_button( + url=main_navigation_url, + icon="home", + title=_("Make Main Navigation"), + name="make-main-navigation", + disabled=disabled, + ) + return render_to_string( "admin/djangocms_navigation/icons/main_navigation.html", {"url": main_navigation_url, "disabled": disabled} From ac0addc157ca483baf98dd1e5cc9c1c1979cd146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Tue, 5 Nov 2024 16:18:49 +0800 Subject: [PATCH 20/22] fix menuitem change form rquired issue. --- djangocms_navigation/admin.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 8618012ae..9885b43c1 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -152,8 +152,7 @@ def is_locked(self, obj): if version.state == DRAFT and version_is_locked(version): if CMS_41: return mark_safe('') - else: - return render_to_string("djangocms_version_locking/admin/locked_icon.html") + return render_to_string("djangocms_version_locking/admin/locked_icon.html") return "" def _get_references_link(self, obj, request): @@ -420,7 +419,6 @@ def _get_edit_link(self, obj, request, disabled=False): title=_("Edit"), name="edit", disabled=disabled, - action="post", keepsideframe=False, ) @@ -445,11 +443,11 @@ def _get_delete_link(self, obj, request, disabled=False): name="discard", disabled=disabled, ) - else: - return render_to_string( - "djangocms_versioning/admin/discard_icon.html", - {"discard_url": delete_url, "disabled": disabled, "object_id": obj.id}, - ) + + return render_to_string( + "djangocms_versioning/admin/icons/discard_icon.html", + {"discard_url": delete_url, "disabled": disabled, "object_id": obj.id}, + ) def get_queryset(self, request): if hasattr(request, "menu_content_id"): From 953c2305dc296536dcf8b965ba4e8302eac3dadf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=82=85=E7=9D=BF=E6=9B=BC?= Date: Wed, 6 Nov 2024 11:08:37 +0800 Subject: [PATCH 21/22] fix 4.0 test issue --- djangocms_navigation/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 9885b43c1..f5f6f294b 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -443,9 +443,9 @@ def _get_delete_link(self, obj, request, disabled=False): name="discard", disabled=disabled, ) - + return render_to_string( - "djangocms_versioning/admin/icons/discard_icon.html", + "djangocms_versioning/admin/discard_icon.html", {"discard_url": delete_url, "disabled": disabled, "object_id": obj.id}, ) From 86ed1799409e26f85c8288addf15481fbaa0fd1b Mon Sep 17 00:00:00 2001 From: Josh Yu Date: Tue, 26 Nov 2024 13:33:56 +0800 Subject: [PATCH 22/22] fix: remove reference of `djangocms_versioning/css/actions.css` --- djangocms_navigation/admin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index f5f6f294b..021646c91 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -91,7 +91,7 @@ class MenuContentAdmin(ExtendedVersionAdminMixin, admin.ModelAdmin): class Media: js = ("admin/js/jquery.init.js", "djangocms_versioning/js/actions.js",) - css = {"all": ("djangocms_versioning/css/actions.css", "djangocms_version_locking/css/version-locking.css",)} + css = {"all": ("djangocms_version_locking/css/version-locking.css",)} def _list_actions(self, request): """ @@ -299,7 +299,6 @@ class MenuItemAdmin(*menuitem_admin_class): class Media: css = { "all": ( - "djangocms_versioning/css/actions.css", "djangocms_navigation/css/navigation_admin_changelist.css", ) }