Skip to content

Commit 09ec934

Browse files
authored
feat: Re-introduce deleting languages of a page (#443)
* feat: Re-introduce deleting languages of a page * Fix ruff issues * Add test for delete tranlsation menu * Single-quoted regex * Only activate delete translation for django CMS version supporting it * fix: Redirect to different language if current translation is deleted * fix setup.py * Update djangocms_versioning/cms_toolbars.py * Update tests * fix linting issue * Add `skipIf` reason * Fix test
1 parent 81306a0 commit 09ec934

File tree

3 files changed

+101
-4
lines changed

3 files changed

+101
-4
lines changed

djangocms_versioning/cms_toolbars.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
from copy import copy
33
from typing import Optional
44

5+
from cms import __version__ as cms_version
56
from cms.cms_toolbars import (
67
ADD_PAGE_LANGUAGE_BREAK,
78
LANGUAGE_MENU_IDENTIFIER,
89
PageToolbar,
910
PlaceholderToolbar,
1011
)
12+
from cms.constants import REFRESH_PAGE
1113
from cms.models import PageContent
1214
from cms.toolbar.items import RIGHT, Break, ButtonList, TemplateItem
1315
from cms.toolbar.utils import get_object_preview_url
@@ -23,8 +25,9 @@
2325
from django.urls import reverse
2426
from django.utils.http import urlencode
2527
from django.utils.translation import gettext_lazy as _
28+
from packaging import version
2629

27-
from djangocms_versioning.conf import LOCK_VERSIONS
30+
from djangocms_versioning.conf import ALLOW_DELETING_VERSIONS, LOCK_VERSIONS
2831
from djangocms_versioning.constants import DRAFT, PUBLISHED
2932
from djangocms_versioning.helpers import (
3033
get_latest_admin_viewable_content,
@@ -33,6 +36,7 @@
3336
from djangocms_versioning.models import Version
3437

3538
VERSIONING_MENU_IDENTIFIER = "version"
39+
CMS_SUPPORTS_DELETING_TRANSLATIONS = version.Version(cms_version) > version.Version("4.1.4")
3640

3741

3842
class VersioningToolbar(PlaceholderToolbar):
@@ -385,6 +389,23 @@ def change_language_menu(self):
385389
)
386390
add_plugins_menu.add_modal_item(name, url=url)
387391

392+
if remove and ALLOW_DELETING_VERSIONS and CMS_SUPPORTS_DELETING_TRANSLATIONS:
393+
remove_plugins_menu = language_menu.get_or_create_menu(
394+
f"{LANGUAGE_MENU_IDENTIFIER}-del", _("Delete Translation")
395+
)
396+
disabled = len(remove) == 1
397+
for code, name in remove:
398+
pagecontent = self.page.get_admin_content(language=code)
399+
if pagecontent:
400+
translation_delete_url = admin_reverse("cms_pagecontent_delete", args=(pagecontent.pk,))
401+
url = add_url_parameters(translation_delete_url, language=code)
402+
on_close = REFRESH_PAGE
403+
if self.toolbar.get_object() == pagecontent and not disabled:
404+
other_content = next((self.page.get_admin_content(lang)for lang in self.page.get_languages()
405+
if lang != pagecontent.language and lang in languages), None)
406+
on_close = get_object_preview_url(other_content)
407+
remove_plugins_menu.add_modal_item(name, url=url, disabled=disabled, on_close=on_close)
408+
388409
if copy:
389410
copy_plugins_menu = language_menu.get_or_create_menu(
390411
f"{LANGUAGE_MENU_IDENTIFIER}-copy", _("Copy all plugins")
@@ -394,7 +415,7 @@ def change_language_menu(self):
394415
item_added = False
395416
for code, name in copy:
396417
# Get the Draft or Published PageContent.
397-
page_content = self.get_page_content(language=code)
418+
page_content = self.page.get_admin_content(language=code)
398419
if page_content: # Only offer to copy if content for source language exists
399420
page_copy_url = admin_reverse("cms_pagecontent_copy_language", args=(page_content.pk,))
400421
copy_plugins_menu.add_ajax_item(

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
INSTALL_REQUIREMENTS = [
66
"Django>=3.2",
77
"django-cms>=4.1.1",
8-
"django-fsm<3"
8+
"django-fsm<3",
9+
"packaging",
910
]
1011

1112
setup(

tests/test_toolbars.py

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
import re
2+
from unittest import skipIf
3+
from unittest.mock import patch
4+
5+
from cms import __version__
16
from cms.cms_toolbars import LANGUAGE_MENU_IDENTIFIER, PlaceholderToolbar
27
from cms.test_utils.testcases import CMSTestCase
38
from cms.toolbar.utils import get_object_edit_url, get_object_preview_url
49
from cms.utils.urlutils import admin_reverse
510
from django.contrib.auth.models import Permission
611
from django.utils.text import slugify
12+
from packaging.version import Version
713

814
from djangocms_versioning.cms_config import VersioningCMSConfig
915
from djangocms_versioning.cms_toolbars import VersioningPageToolbar
@@ -26,6 +32,8 @@
2632
toolbar_button_exists,
2733
)
2834

35+
cms_version = Version(__version__)
36+
2937

3038
class VersioningToolbarTestCase(CMSTestCase):
3139
def _get_publish_url(self, version, versionable=PollsCMSConfig.versioning[0]):
@@ -488,7 +496,7 @@ def _get_toolbar_item_by_name(self, menu, name):
488496

489497
def test_change_language_menu_page_toolbar(self):
490498
"""Check that patched PageToolbar.change_language_menu only provides
491-
Add Translation links.
499+
Add Translation links if DJANGOCMS_ALLOW_DELETING_VERSIONS is False.
492500
"""
493501
version = PageVersionFactory(content__language="en")
494502
PageContentWithVersionFactory(page=version.content.page, language="de")
@@ -533,6 +541,73 @@ def test_change_language_menu_page_toolbar(self):
533541
lang_code = "fr" if "Française" in item.name else "it"
534542
self.assertIn(f"language={lang_code}", item.url)
535543

544+
@skipIf(cms_version <= Version("4.1.4"), "For CMS 4.1.5 and bove: Add delete translation menu")
545+
def test_change_language_menu_page_toolbar_including_delete(self):
546+
"""Check that patched PageToolbar.change_language_menu also provides
547+
Delete Translation links if DJANGOCMS_ALLOW_DELETING_VERSIONS is True.
548+
"""
549+
from djangocms_versioning import cms_toolbars
550+
551+
with patch.object(cms_toolbars, "ALLOW_DELETING_VERSIONS", True):
552+
version = PageVersionFactory(content__language="en")
553+
PageContentWithVersionFactory(page=version.content.page, language="de")
554+
PageContentWithVersionFactory(page=version.content.page, language="it")
555+
page = version.content.page
556+
page.update_languages(["en", "de", "it"])
557+
558+
request = self.get_page_request(
559+
page=page,
560+
path=get_object_edit_url(version.content),
561+
user=self.get_superuser(),
562+
)
563+
request.toolbar.set_object(version.content)
564+
request.toolbar.populate()
565+
request.toolbar.post_template_populate()
566+
567+
language_menu = request.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER)
568+
# 3 out of 4 populated languages, Break, Add Translation menu, Copy all plugins
569+
self.assertEqual(language_menu.get_item_count(), 7)
570+
571+
language_menu_dict = {
572+
menu.name: list(menu.items)
573+
for key, menu in language_menu.menus.items()
574+
}
575+
self.assertIn("Add Translation", language_menu_dict.keys())
576+
self.assertIn("Copy all plugins", language_menu_dict.keys())
577+
self.assertIn("Delete Translation", language_menu_dict.keys())
578+
579+
pattern = r"\?language=([a-z]{2})"
580+
for item in language_menu_dict["Delete Translation"]:
581+
match = re.search(pattern, item.url) # Contains "?language=<code>“?
582+
self.assertTrue(bool(match))
583+
code = match.group(1) # Extract code
584+
pk = page.get_admin_content(code).pk # get content object
585+
self.assertIn(admin_reverse("cms_pagecontent_delete", args=(int(pk),)), item.url) # verify url
586+
587+
@skipIf(cms_version > Version("4.1.4"), "Only for CMS 4.1.4 and below: No delete translation menu")
588+
def test_change_language_menu_page_toolbar_excluding_delete(self):
589+
from djangocms_versioning import cms_toolbars
590+
591+
with patch.object(cms_toolbars, "ALLOW_DELETING_VERSIONS", True):
592+
version = PageVersionFactory(content__language="en")
593+
PageContentWithVersionFactory(page=version.content.page, language="de")
594+
PageContentWithVersionFactory(page=version.content.page, language="it")
595+
page = version.content.page
596+
page.update_languages(["en", "de", "it"])
597+
598+
request = self.get_page_request(
599+
page=page,
600+
path=get_object_edit_url(version.content),
601+
user=self.get_superuser(),
602+
)
603+
request.toolbar.set_object(version.content)
604+
request.toolbar.populate()
605+
request.toolbar.post_template_populate()
606+
607+
language_menu = request.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER)
608+
# 3 out of 4 populated languages, Break, Add Translation menu, Copy all plugins
609+
self.assertEqual(language_menu.get_item_count(), 6)
610+
536611
def test_change_language_menu_page_toolbar_language_selector_version_link(self):
537612
"""
538613
Ensure that the correct version is navigated to in the language selector.

0 commit comments

Comments
 (0)