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