diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5e32787b1..bce3eb798 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,7 +7,7 @@ Unreleased * Python 3.10 support added * Python 3.7 support removed * Django 4.2 support added -* Djanjo 2.2 support removed +* Django 2.2 support removed 1.8.3 (2024-03-06) ================== diff --git a/README.rst b/README.rst index d65bc4796..eca4dc87f 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ ==================== -djangocms-navigation +djangocms-navigation ==================== Installation diff --git a/djangocms_navigation/admin.py b/djangocms_navigation/admin.py index 4279b4bd4..e6f6846be 100644 --- a/djangocms_navigation/admin.py +++ b/djangocms_navigation/admin.py @@ -26,6 +26,7 @@ from djangocms_versioning.models import Version from treebeard.admin import TreeAdmin +from .compat import TREEBEARD_4_5 from .conf import TREE_MAX_RESULT_PER_PAGE_COUNT from .filters import LanguageFilter from .forms import MenuContentForm, MenuItemForm @@ -498,7 +499,10 @@ def get_changelist_template(self, request): """ if is_preview_url(request=request): return "admin/djangocms_navigation/menuitem/preview.html" - return "admin/djangocms_navigation/menuitem/change_list.html" + elif TREEBEARD_4_5: + return "admin/djangocms_navigation/menuitem/change_list.html" + else: + return "admin/djangocms_navigation/menuitem/tree_change_list.html" def changelist_view(self, request, menu_content_id=None, extra_context=None): self.change_list_template = self.get_changelist_template(request=request) diff --git a/djangocms_navigation/compat.py b/djangocms_navigation/compat.py index f2c5cad01..3517f7d59 100644 --- a/djangocms_navigation/compat.py +++ b/djangocms_navigation/compat.py @@ -1,6 +1,5 @@ -import django - from packaging.version import Version +from treebeard import __version__ as treebeard_version -DJANGO_4_2 = Version(django.get_version()) >= Version('4.2') +TREEBEARD_4_5 = Version(treebeard_version) < Version('4.6') diff --git a/djangocms_navigation/static/djangocms_navigation/js/navigation-tree-admin.js b/djangocms_navigation/static/djangocms_navigation/js/navigation-tree-admin.js index f8513ce95..3f8aef78e 100644 --- a/djangocms_navigation/static/djangocms_navigation/js/navigation-tree-admin.js +++ b/djangocms_navigation/static/djangocms_navigation/js/navigation-tree-admin.js @@ -14,6 +14,26 @@ Original code found in treebeard-admin.js const EXPANDED_SESSION_KEY = 'expanded-'; + // Add jQuery util for disabling selection + // Originally taken from jquery-ui (where it is deprecated) + // https://api.jqueryui.com/disableSelection/ + if($.fn.disableSelection == undefined) { + $.fn.extend( { + disableSelection: ( function() { + var eventType = "onselectstart" in document.createElement( "div" ) ? "selectstart" : "mousedown"; + return function() { + return this.on( eventType + ".ui-disableSelection", function( event ) { + event.preventDefault(); + } ); + }; + } )(), + + enableSelection: function() { + return this.off( ".ui-disableSelection" ); + } + } ); + } + // This is the basic Node class, which handles UI tree operations for each 'row' var Node = function (elem) { var $elem = $(elem); @@ -146,7 +166,7 @@ Original code found in treebeard-admin.js if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); + var cookie = $.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); diff --git a/djangocms_navigation/templates/admin/djangocms_navigation/menuitem/tree_change_list.html b/djangocms_navigation/templates/admin/djangocms_navigation/menuitem/tree_change_list.html new file mode 100644 index 000000000..e3300135e --- /dev/null +++ b/djangocms_navigation/templates/admin/djangocms_navigation/menuitem/tree_change_list.html @@ -0,0 +1,45 @@ +{# copy from djangocms-treebeard tree_change_list.html to override media files #} +{% extends "admin/change_list.html" %} +{% load static admin_list admin_tree admin_urls navigation_admin_tree i18n djangocms_versioning %} + +{% block extrastyle %} + {{ block.super }} + + +{% endblock %} + +{% block extrahead %} + {{ block.super }} + + +{% endblock %} + +{% block result_list %} + {% if action_form and actions_on_top and cl.full_result_count %} + {% admin_actions %} + {% endif %} + {% result_tree cl request %} + {% if action_form and actions_on_bottom and cl.full_result_count %} + {% admin_actions %} + {% endif %} +{% endblock %} + +{% block object-tools-items %} +
  • + + {% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %} + +
  • +
  • + + {% trans "Preview" %} + +
  • +{% if versioning_enabled_for_nav %} +
  • + + {% trans "Versions" %} + +
  • +{% endif %} +{% endblock %} diff --git a/djangocms_navigation/templatetags/navigation_admin_tree.py b/djangocms_navigation/templatetags/navigation_admin_tree.py index e13f0191d..58467bd26 100644 --- a/djangocms_navigation/templatetags/navigation_admin_tree.py +++ b/djangocms_navigation/templatetags/navigation_admin_tree.py @@ -5,6 +5,7 @@ result_hidden_fields, ) from django.templatetags.static import static +from django.urls import reverse from django.utils.html import format_html from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ @@ -104,7 +105,7 @@ def treebeard_js(): """ js_file = static('djangocms_navigation/js/navigation-tree-admin.js') - + jsi18n_url = reverse('admin:jsi18n') jquery_ui = static('treebeard/jquery-ui-1.8.5.custom.min.js') # Jquery UI is needed to call disableSelection() on drag and drop so @@ -118,7 +119,7 @@ def treebeard_js(): '' '') return format_html( - TEMPLATE, "jsi18n", mark_safe(js_file), mark_safe(jquery_ui)) + TEMPLATE, jsi18n_url, mark_safe(js_file), mark_safe(jquery_ui)) admin_tree.treebeard_js = treebeard_js diff --git a/tests/requirements/dj32_cms40.txt b/tests/requirements/dj32_cms40.txt index 0a44ecaf4..1ab41c37f 100644 --- a/tests/requirements/dj32_cms40.txt +++ b/tests/requirements/dj32_cms40.txt @@ -1,3 +1,4 @@ -r ./requirements_base.txt Django>=3.2,<4.0 +django-treebeard<=4.5.1 \ No newline at end of file diff --git a/tests/requirements/dj42_cms40.txt b/tests/requirements/dj42_cms40.txt index 95ebb5ac4..6552862ad 100644 --- a/tests/requirements/dj42_cms40.txt +++ b/tests/requirements/dj42_cms40.txt @@ -1,3 +1,4 @@ -r ./requirements_base.txt Django>=4.2,<5.0 +django-treebeard>=4.6.0 \ No newline at end of file diff --git a/tests/settings.py b/tests/settings.py index 03f0e556c..b55fb8341 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -43,9 +43,8 @@ def run(): from app_helper import runner runner.cms("djangocms_navigation", extra_args=[]) from cms.test_utils.testcases import CMSTestCase - - from djangocms_navigation.compat import DJANGO_4_2 - if not DJANGO_4_2: + from cms.utils.compat import DJANGO_4_1 + if DJANGO_4_1: CMSTestCase.assertQuerySetEqual = CMSTestCase.assertQuerysetEqual diff --git a/tests/test_admin.py b/tests/test_admin.py index b93e2705b..8a0466c40 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -2,6 +2,7 @@ import importlib import json import sys +from unittest import skipIf, skipUnless from unittest.mock import patch from django.contrib import admin @@ -16,6 +17,7 @@ from cms.api import add_plugin, create_page, create_title 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 @@ -28,7 +30,7 @@ MenuItemAdmin, MenuItemChangeList, ) -from djangocms_navigation.compat import DJANGO_4_2 +from djangocms_navigation.compat import TREEBEARD_4_5 from djangocms_navigation.models import Menu, MenuContent, MenuItem from djangocms_navigation.test_utils import factories @@ -65,7 +67,7 @@ def _get_changelist_instance(self, menu_content): model_admin, # model_admin admin_field, # sortable_by ] - if DJANGO_4_2: + if not DJANGO_4_1: search_help_text = model_admin.search_help_text args.append(search_help_text) @@ -330,7 +332,19 @@ def test_get_list_display(self): ['__str__', 'get_object_url', 'soft_root', 'hide_node', "list_actions"] ) - def test_get_changelist_template(self): + @skipIf(TREEBEARD_4_5, "Test relevant only for treebeard>=4.6") + def test_get_changelist_template_for_old_treebeard(self): + """ + Check the template is the standard change list template when the request is for the changelist endpoint + """ + request = self.get_request("/admin/djangocms_navigation/menuitem/1/") + + result = self.model_admin.get_changelist_template(request=request) + + self.assertEqual(result, "admin/djangocms_navigation/menuitem/tree_change_list.html") + + @skipUnless(TREEBEARD_4_5, "Test relevant only for treebeard<4.6") + def test_get_changelist_template_for_new_treebeard(self): """ Check the template is the standard change list template when the request is for the changelist endpoint """ diff --git a/tests/test_forms.py b/tests/test_forms.py index a86334fab..5d43b8284 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -3,9 +3,9 @@ from cms.models import Page from cms.test_utils.testcases import CMSTestCase +from cms.utils.compat import DJANGO_4_1 from cms.utils.urlutils import admin_reverse -from djangocms_navigation.compat import DJANGO_4_2 from djangocms_navigation.constants import SELECT2_CONTENT_OBJECT_URL_NAME from djangocms_navigation.forms import ( ContentTypeObjectSelectWidget, @@ -17,7 +17,7 @@ from djangocms_navigation.test_utils.polls.models import PollContent -if not DJANGO_4_2: +if DJANGO_4_1: CMSTestCase.assertQuerySetEqual = CMSTestCase.assertQuerysetEqual