forked from ungleich-public/dynamicweb
clone cms with menus, make menus standalone app
This commit is contained in:
parent
1ece5ce7c7
commit
afb096b7a3
1153 changed files with 318897 additions and 37 deletions
730
cms/cms_toolbars.py
Normal file
730
cms/cms_toolbars.py
Normal file
|
|
@ -0,0 +1,730 @@
|
|||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth import get_permission_codename, get_user_model
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.sites.models import Site
|
||||
from django.urls import NoReverseMatch, Resolver404, resolve, reverse
|
||||
from django.utils.translation import (
|
||||
gettext_lazy as _,
|
||||
override as force_language,
|
||||
)
|
||||
|
||||
from cms.api import can_change_page
|
||||
from cms.constants import TEMPLATE_INHERITANCE_MAGIC
|
||||
from cms.models import Page, PageContent, PageType, Placeholder
|
||||
from cms.toolbar.items import REFRESH_PAGE, ButtonList, SubMenu, TemplateItem
|
||||
from cms.toolbar.utils import (
|
||||
get_object_edit_url,
|
||||
get_object_preview_url,
|
||||
get_object_structure_url,
|
||||
)
|
||||
from cms.toolbar_base import CMSToolbar
|
||||
from cms.toolbar_pool import toolbar_pool
|
||||
from cms.utils import get_language_from_request, page_permissions
|
||||
from cms.utils.conf import get_cms_setting
|
||||
from cms.utils.i18n import get_language_dict, get_language_tuple
|
||||
from cms.utils.page_permissions import (
|
||||
user_can_change_page,
|
||||
user_can_delete_page,
|
||||
user_can_view_page,
|
||||
)
|
||||
from cms.utils.permissions import user_can_view_placeholder_source
|
||||
from cms.utils.urlutils import add_url_parameters, admin_reverse
|
||||
from menus.utils import DefaultLanguageChanger
|
||||
|
||||
# Identifiers for search
|
||||
ADMIN_MENU_IDENTIFIER = "admin-menu"
|
||||
"""
|
||||
The *Site* menu (that usually shows the project's domain name, *example.com* by default).
|
||||
``ADMIN_MENU_IDENTIFIER`` allows you to get hold of this object easily using
|
||||
:meth:`cms.toolbar.toolbar.CMSToolbar.get_menu`.
|
||||
"""
|
||||
LANGUAGE_MENU_IDENTIFIER = "language-menu"
|
||||
"""
|
||||
The *Language* menu. ``LANGUAGE_MENU_IDENTIFIER`` allows you to get hold of this object
|
||||
easily using :meth:`cms.toolbar.toolbar.CMSToolbar.get_menu`.
|
||||
"""
|
||||
HELP_MENU_IDENTIFIER = "help-menu"
|
||||
"""
|
||||
The *Help* menu. ``HELP_MENU_IDENTIFIER`` allows you to get hold of this object easily
|
||||
using :meth:`cms.toolbar.toolbar.CMSToolbar.get_menu`.
|
||||
"""
|
||||
HELP_MENU_BREAK = "Help Menu Break"
|
||||
TEMPLATE_MENU_BREAK = "Template Menu Break"
|
||||
PAGE_MENU_IDENTIFIER = "page"
|
||||
"""
|
||||
The *Page* menu. ``PAGE_MENU_IDENTIFIER`` allows you to get hold of this object
|
||||
easily using :meth:`cms.toolbar.toolbar.CMSToolbar.get_menu`.
|
||||
"""
|
||||
PAGE_MENU_ADD_IDENTIFIER = "add_page"
|
||||
PAGE_MENU_FIRST_BREAK = "Page Menu First Break"
|
||||
PAGE_MENU_SECOND_BREAK = "Page Menu Second Break"
|
||||
PAGE_MENU_THIRD_BREAK = "Page Menu Third Break"
|
||||
PAGE_MENU_FOURTH_BREAK = "Page Menu Fourth Break"
|
||||
PAGE_MENU_LAST_BREAK = "Page Menu Last Break"
|
||||
HISTORY_MENU_BREAK = "History Menu Break"
|
||||
MANAGE_PAGES_BREAK = "Manage Pages Break"
|
||||
ADMIN_SITES_BREAK = "Admin Sites Break"
|
||||
ADMINISTRATION_BREAK = "Administration Break"
|
||||
CLIPBOARD_BREAK = "Clipboard Break"
|
||||
USER_SETTINGS_BREAK = "User Settings Break"
|
||||
ADD_PAGE_LANGUAGE_BREAK = "Add page language Break"
|
||||
REMOVE_PAGE_LANGUAGE_BREAK = "Remove page language Break"
|
||||
COPY_PAGE_LANGUAGE_BREAK = "Copy page language Break"
|
||||
TOOLBAR_DISABLE_BREAK = "Toolbar disable Break"
|
||||
SHORTCUTS_BREAK = "Shortcuts Break"
|
||||
|
||||
DEFAULT_HELP_MENU_ITEMS = (
|
||||
(_("Documentation"), "https://docs.django-cms.org/en/stable/"),
|
||||
(_("User guide"), "https://user-guide.django-cms.org"),
|
||||
(_("Discord community"), "https://www.django-cms.org/discord"),
|
||||
(_("What's new"), "https://www.django-cms.org/en/blog/"),
|
||||
)
|
||||
|
||||
|
||||
@toolbar_pool.register
|
||||
class PlaceholderToolbar(CMSToolbar):
|
||||
"""
|
||||
Adds placeholder edit buttons if placeholders or static placeholders are detected in the template
|
||||
"""
|
||||
|
||||
def populate(self):
|
||||
self.page = self.request.current_page
|
||||
|
||||
def post_template_populate(self):
|
||||
super().post_template_populate()
|
||||
self.add_wizard_button()
|
||||
self.render_object_editable_buttons()
|
||||
|
||||
def add_wizard_button(self):
|
||||
from cms.wizards.wizard_pool import entry_choices
|
||||
|
||||
title = _("Create")
|
||||
|
||||
user = self.request.user
|
||||
page_pk = self.page.pk if self.page else ""
|
||||
disabled = not list(entry_choices(user, self.page, site=self.current_site))
|
||||
|
||||
url = "{url}?page={page}&language={lang}&edit".format(
|
||||
url=admin_reverse("cms_wizard_create"),
|
||||
page=page_pk,
|
||||
lang=self.toolbar.site_language,
|
||||
)
|
||||
self.toolbar.add_modal_button(title, url, side=self.toolbar.RIGHT, disabled=disabled, on_close=REFRESH_PAGE)
|
||||
|
||||
def render_object_editable_buttons(self):
|
||||
self.init_placeholders()
|
||||
|
||||
if not self.toolbar.obj:
|
||||
return
|
||||
|
||||
# Edit button
|
||||
if self.toolbar.content_mode_active and self._can_add_button():
|
||||
self.add_edit_button()
|
||||
# Preview button
|
||||
if not self.toolbar.preview_mode_active and get_cms_setting("TEMPLATES") and self._can_add_button():
|
||||
# Only add preview button if there are templates available for previewing
|
||||
self.add_preview_button()
|
||||
# Structure mode
|
||||
if self._can_add_structure_mode():
|
||||
self.add_structure_mode()
|
||||
|
||||
def init_placeholders(self):
|
||||
request = self.request
|
||||
toolbar = self.toolbar
|
||||
|
||||
if toolbar._async and "placeholders[]" in request.GET:
|
||||
# AJAX request to reload page structure.
|
||||
placeholder_ids = request.GET.getlist("placeholders[]")
|
||||
self.placeholders = Placeholder.objects.filter(pk__in=placeholder_ids)
|
||||
else:
|
||||
if toolbar.structure_mode_active and not toolbar.uses_legacy_structure_mode:
|
||||
# User has explicitly requested structure mode.
|
||||
# and the object (page, blog, etc..) allows for the non-legacy structure mode.
|
||||
renderer = toolbar.structure_renderer
|
||||
else:
|
||||
renderer = toolbar.get_content_renderer()
|
||||
|
||||
self.placeholders = renderer.get_rendered_placeholders()
|
||||
|
||||
# Helpers to check whether buttons can be rendered
|
||||
def _has_page_change_perm(self):
|
||||
if self.page and user_can_change_page(self.request.user, page=self.page):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _has_placeholder_change_perm(self):
|
||||
if not self.placeholders:
|
||||
return False
|
||||
return any(ph for ph in self.placeholders if ph.has_change_permission(self.request.user))
|
||||
|
||||
def _has_page_view_perm(self):
|
||||
if self.page and user_can_view_page(self.request.user, self.page):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _has_placeholder_view_perm(self):
|
||||
obj = self.toolbar.obj
|
||||
if obj is None:
|
||||
return False
|
||||
return user_can_view_placeholder_source(self.request.user, obj)
|
||||
|
||||
def _can_add_button(self):
|
||||
if self._has_page_change_perm():
|
||||
return True
|
||||
elif self._has_placeholder_change_perm():
|
||||
return True
|
||||
return False
|
||||
|
||||
def _can_add_structure_mode(self):
|
||||
# Viewing the structure board only requires view permission: editing
|
||||
# the plugins stays gated by change permission at the plugin endpoints.
|
||||
# This lets headless reviewers (and view-only staff) inspect content
|
||||
# structure without edit rights.
|
||||
if not self.request.user.has_perm("cms.use_structure"):
|
||||
return False
|
||||
|
||||
if self.page and not self.page.application_urls and self._has_page_view_perm():
|
||||
return True
|
||||
elif self._has_placeholder_view_perm():
|
||||
return True
|
||||
return False
|
||||
|
||||
# Buttons
|
||||
def add_edit_button(self):
|
||||
url = get_object_edit_url(self.toolbar.obj, language=self.toolbar.request_language, params=self.request.GET)
|
||||
item = ButtonList(side=self.toolbar.RIGHT)
|
||||
item.add_button(
|
||||
_("Edit"),
|
||||
url=url,
|
||||
disabled=False,
|
||||
extra_classes=["cms-btn", "cms-btn-action", "cms-btn-switch-edit"],
|
||||
)
|
||||
self.toolbar.add_item(item)
|
||||
|
||||
def add_preview_button(self):
|
||||
url = get_object_preview_url(self.toolbar.obj, language=self.toolbar.request_language, params=self.request.GET)
|
||||
if url:
|
||||
item = ButtonList(side=self.toolbar.RIGHT)
|
||||
item.add_button(
|
||||
_("Preview"),
|
||||
url=url,
|
||||
disabled=False,
|
||||
extra_classes=["cms-btn", "cms-btn-switch-save"],
|
||||
)
|
||||
self.toolbar.add_item(item)
|
||||
|
||||
def add_structure_mode(self, extra_classes=("cms-toolbar-item-cms-mode-switcher",)):
|
||||
structure_active = self.toolbar.structure_mode_active
|
||||
edit_mode_active = not structure_active and self.toolbar.edit_mode_active
|
||||
build_url = get_object_structure_url(
|
||||
self.toolbar.obj, language=self.toolbar.request_language, params=self.request.GET
|
||||
)
|
||||
edit_url = get_object_edit_url(
|
||||
self.toolbar.obj, language=self.toolbar.request_language, params=self.request.GET
|
||||
)
|
||||
switcher = self.toolbar.add_button_list(
|
||||
"Mode Switcher",
|
||||
side=self.toolbar.RIGHT,
|
||||
extra_classes=extra_classes,
|
||||
)
|
||||
switcher.add_button(
|
||||
_("Structure"),
|
||||
build_url,
|
||||
active=structure_active,
|
||||
disabled=False,
|
||||
extra_classes="cms-structure-btn",
|
||||
)
|
||||
switcher.add_button(
|
||||
_("Content"),
|
||||
edit_url,
|
||||
active=edit_mode_active,
|
||||
disabled=False,
|
||||
extra_classes="cms-content-btn",
|
||||
)
|
||||
|
||||
|
||||
@toolbar_pool.register
|
||||
class AppearanceToolbar(CMSToolbar):
|
||||
"""
|
||||
Adds appearance switches, esp. for dark and light mode
|
||||
"""
|
||||
|
||||
color_scheme_toggle = get_cms_setting("COLOR_SCHEME_TOGGLE")
|
||||
|
||||
def populate(self):
|
||||
if self.color_scheme_toggle:
|
||||
dark_mode_toggle = TemplateItem(
|
||||
template="cms/toolbar/items/dark_mode_toggle.html",
|
||||
side=self.toolbar.RIGHT,
|
||||
)
|
||||
self.toolbar.add_item(dark_mode_toggle)
|
||||
|
||||
|
||||
@toolbar_pool.register
|
||||
class HelpToolbar(CMSToolbar):
|
||||
"""
|
||||
Adds a help menu to the toolbar
|
||||
"""
|
||||
|
||||
def populate(self):
|
||||
if not get_cms_setting("ENABLE_HELP"):
|
||||
return
|
||||
help_menu = self._get_or_create_help_menu()
|
||||
self._add_default_menu_items(help_menu)
|
||||
self._add_extra_menu_items(help_menu)
|
||||
|
||||
def _get_or_create_help_menu(self) -> SubMenu:
|
||||
help_menu = self.toolbar.get_or_create_menu(HELP_MENU_IDENTIFIER, _("Help"), position=-1)
|
||||
help_menu.items = [] # reset the items so we don't duplicate
|
||||
return help_menu
|
||||
|
||||
def _add_default_menu_items(self, help_menu: SubMenu):
|
||||
for label, url in DEFAULT_HELP_MENU_ITEMS:
|
||||
help_menu.add_link_item(label, url=url)
|
||||
|
||||
def _add_extra_menu_items(self, help_menu: SubMenu):
|
||||
if extra_menu_items := get_cms_setting("EXTRA_HELP_MENU_ITEMS"):
|
||||
help_menu.add_break(HELP_MENU_BREAK)
|
||||
for label, url in extra_menu_items:
|
||||
help_menu.add_link_item(label, url=url)
|
||||
|
||||
|
||||
@toolbar_pool.register
|
||||
class BasicToolbar(CMSToolbar):
|
||||
"""
|
||||
Basic Toolbar for site and languages menu
|
||||
"""
|
||||
|
||||
page = None
|
||||
_language_menu = None
|
||||
_admin_menu = None
|
||||
|
||||
def init_from_request(self):
|
||||
self.page = self.request.current_page
|
||||
|
||||
def populate(self):
|
||||
if not self.page:
|
||||
self.init_from_request()
|
||||
self.clipboard = self.request.toolbar.user_settings.clipboard
|
||||
self.add_admin_menu()
|
||||
self.add_language_menu()
|
||||
|
||||
def add_admin_menu(self):
|
||||
if not self._admin_menu:
|
||||
self._admin_menu = self.toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, self.current_site.name)
|
||||
# Users button
|
||||
self.add_users_button(self._admin_menu)
|
||||
|
||||
# sites menu
|
||||
sites_queryset = Site.objects.order_by("name")
|
||||
|
||||
if len(sites_queryset) > 1:
|
||||
sites_menu = self._admin_menu.get_or_create_menu("sites", _("Sites"))
|
||||
sites_menu.add_sideframe_item(_("Admin Sites"), url=admin_reverse("sites_site_changelist"))
|
||||
sites_menu.add_break(ADMIN_SITES_BREAK)
|
||||
for site in sites_queryset:
|
||||
sites_menu.add_link_item(
|
||||
site.name, url="//%s" % site.domain, active=site.pk == self.current_site.pk
|
||||
)
|
||||
|
||||
# admin
|
||||
self._admin_menu.add_sideframe_item(_("Administration"), url=admin_reverse("index"))
|
||||
self._admin_menu.add_break(ADMINISTRATION_BREAK)
|
||||
|
||||
# cms users settings
|
||||
self._admin_menu.add_sideframe_item(_("User settings"), url=admin_reverse("cms_usersettings_change"))
|
||||
self._admin_menu.add_break(USER_SETTINGS_BREAK)
|
||||
|
||||
# clipboard
|
||||
if self.toolbar.edit_mode_active:
|
||||
# True if the clipboard exists and there's plugins in it.
|
||||
clipboard_is_bound = self.toolbar.clipboard_plugin
|
||||
|
||||
self._admin_menu.add_link_item(
|
||||
_("Clipboard..."),
|
||||
url="#",
|
||||
extra_classes=["cms-clipboard-trigger"],
|
||||
disabled=not clipboard_is_bound,
|
||||
)
|
||||
self._admin_menu.add_link_item(
|
||||
_("Clear clipboard"),
|
||||
url="#",
|
||||
extra_classes=["cms-clipboard-empty"],
|
||||
disabled=not clipboard_is_bound,
|
||||
)
|
||||
self._admin_menu.add_break(CLIPBOARD_BREAK)
|
||||
|
||||
# Disable toolbar
|
||||
self._admin_menu.add_link_item(
|
||||
_("Disable toolbar"), url="?%s" % get_cms_setting("CMS_TOOLBAR_URL__DISABLE")
|
||||
)
|
||||
self._admin_menu.add_break(TOOLBAR_DISABLE_BREAK)
|
||||
self._admin_menu.add_link_item(_("Shortcuts..."), url="#", extra_classes=("cms-show-shortcuts",))
|
||||
self._admin_menu.add_break(SHORTCUTS_BREAK)
|
||||
|
||||
# logout
|
||||
self.add_logout_button(self._admin_menu)
|
||||
|
||||
def add_users_button(self, parent):
|
||||
User = get_user_model()
|
||||
|
||||
if User in admin.site._registry:
|
||||
opts = User._meta
|
||||
|
||||
if self.request.user.has_perm("{}.{}".format(opts.app_label, get_permission_codename("change", opts))):
|
||||
user_changelist_url = admin_reverse(f"{opts.app_label}_{opts.model_name}_changelist")
|
||||
parent.add_sideframe_item(_("Users"), url=user_changelist_url)
|
||||
|
||||
def add_logout_button(self, parent):
|
||||
if self.page and not self.page.login_required:
|
||||
anon_can_access = page_permissions.user_can_view_page(
|
||||
user=AnonymousUser(),
|
||||
page=self.page,
|
||||
site=self.current_site,
|
||||
)
|
||||
else:
|
||||
anon_can_access = False
|
||||
|
||||
on_success = self.toolbar.REFRESH_PAGE if anon_can_access else "/"
|
||||
|
||||
# We'll show "Logout Joe Bloggs" if the name fields in auth.User are completed, else "Logout jbloggs". If
|
||||
# anything goes wrong, it'll just be "Logout".
|
||||
|
||||
user_name = self.get_username()
|
||||
logout_menu_text = _("Logout %s") % user_name if user_name else _("Logout")
|
||||
|
||||
parent.add_ajax_item(
|
||||
logout_menu_text,
|
||||
action=admin_reverse("logout"),
|
||||
active=True,
|
||||
on_success=on_success,
|
||||
method="POST",
|
||||
)
|
||||
|
||||
def add_language_menu(self):
|
||||
if settings.USE_I18N and not self._language_menu:
|
||||
languages = get_language_tuple(self.current_site.pk)
|
||||
if len(languages) > 1:
|
||||
# Menu only meaningful if more than one language is installed
|
||||
self._language_menu = self.toolbar.get_or_create_menu(
|
||||
LANGUAGE_MENU_IDENTIFIER, _("Language"), position=-1
|
||||
)
|
||||
language_changer = getattr(self.request, "_language_changer", DefaultLanguageChanger(self.request))
|
||||
for code, name in languages:
|
||||
try:
|
||||
url = language_changer(code)
|
||||
except NoReverseMatch:
|
||||
url = DefaultLanguageChanger(self.request)(code)
|
||||
if url:
|
||||
self._language_menu.add_link_item(name, url=url, active=self.current_lang == code)
|
||||
else:
|
||||
# We do not have to check every time the toolbar is created
|
||||
self._language_menu = True # Pretend the language menu is already there
|
||||
|
||||
def get_username(self, user=None, default=""):
|
||||
user = user or self.request.user
|
||||
try:
|
||||
name = user.get_full_name()
|
||||
if name:
|
||||
return name
|
||||
else:
|
||||
return user.get_username()
|
||||
except (AttributeError, NotImplementedError):
|
||||
return default
|
||||
|
||||
|
||||
@toolbar_pool.register
|
||||
class PageToolbar(CMSToolbar):
|
||||
_changed_admin_menu = None
|
||||
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_admin_content(language=self.current_lang, fallback=False)
|
||||
return page_content or None
|
||||
|
||||
def has_page_change_permission(self):
|
||||
if not hasattr(self, "page_change_permission"):
|
||||
self.page_change_permission = can_change_page(self.request) and self.toolbar.object_is_editable()
|
||||
return self.page_change_permission
|
||||
|
||||
def in_apphook(self):
|
||||
with force_language(self.toolbar.request_language):
|
||||
try:
|
||||
resolver = resolve(self.toolbar.request_path)
|
||||
except Resolver404:
|
||||
return False
|
||||
else:
|
||||
cms_views = ("render_object_edit", "render_object_preview", "render_object_structure", "details")
|
||||
return resolver.func.__name__ not in cms_views
|
||||
|
||||
def in_apphook_root(self):
|
||||
"""
|
||||
Returns True if the request is for a page handled by an apphook, but
|
||||
is also the page it is attached to.
|
||||
:return: Boolean
|
||||
"""
|
||||
page = getattr(self.request, "current_page", False)
|
||||
if page:
|
||||
language = get_language_from_request(self.request)
|
||||
return self.toolbar.request_path == page.get_absolute_url(language=language)
|
||||
return False
|
||||
|
||||
def get_on_delete_redirect_url(self):
|
||||
language = self.current_lang
|
||||
parent_page = self.page.parent if self.page else None
|
||||
|
||||
# if the current page has a parent in the request's current language redirect to it
|
||||
if parent_page and language in parent_page.get_languages():
|
||||
return get_object_preview_url(
|
||||
parent_page.pagecontent_set(manager="admin_manager").latest_content(language=language).first()
|
||||
)
|
||||
|
||||
# else redirect to root, do not redirect to Page.objects.get_home() because user could have deleted the last
|
||||
# page, if DEBUG == False this could cause a 404
|
||||
try:
|
||||
return reverse("pages-root")
|
||||
except NoReverseMatch:
|
||||
return admin_reverse("cms_pagecontent_changelist")
|
||||
|
||||
# Populate
|
||||
def populate(self):
|
||||
self.page = self.request.current_page
|
||||
self.page_content = self.get_page_content()
|
||||
self.permissions_activated = get_cms_setting("PERMISSION")
|
||||
self.change_admin_menu()
|
||||
self.add_page_menu()
|
||||
self.change_language_menu()
|
||||
|
||||
# Menus
|
||||
def change_language_menu(self):
|
||||
if self.toolbar.edit_mode_active and self.page:
|
||||
can_change = page_permissions.user_can_change_page(
|
||||
user=self.request.user,
|
||||
page=self.page,
|
||||
site=self.current_site,
|
||||
)
|
||||
else:
|
||||
can_change = False
|
||||
if can_change:
|
||||
language_menu = self.toolbar.get_menu(LANGUAGE_MENU_IDENTIFIER)
|
||||
if not language_menu:
|
||||
return None
|
||||
|
||||
languages = get_language_dict(self.current_site.pk)
|
||||
|
||||
remove = [(code, languages.get(code, code)) for code in self.page.get_languages() if code in languages]
|
||||
add = [lang for lang in languages.items() if lang not in remove]
|
||||
copy = [
|
||||
(code, name)
|
||||
for code, name in languages.items()
|
||||
if code != self.current_lang and (code, name) in remove
|
||||
]
|
||||
|
||||
if add or remove or copy:
|
||||
language_menu.add_break(ADD_PAGE_LANGUAGE_BREAK)
|
||||
|
||||
if add:
|
||||
add_plugins_menu = language_menu.get_or_create_menu(
|
||||
f"{LANGUAGE_MENU_IDENTIFIER}-add", _("Add Translation")
|
||||
)
|
||||
|
||||
page_add_url = admin_reverse("cms_pagecontent_add")
|
||||
|
||||
for code, name in add:
|
||||
url = add_url_parameters(
|
||||
page_add_url, cms_page=self.page.pk, parent_page=self.page.id, language=code
|
||||
)
|
||||
add_plugins_menu.add_modal_item(name, url=url)
|
||||
|
||||
if remove:
|
||||
remove_plugins_menu = language_menu.get_or_create_menu(
|
||||
f"{LANGUAGE_MENU_IDENTIFIER}-del", _("Delete Translation")
|
||||
)
|
||||
disabled = len(remove) == 1
|
||||
for code, name in remove:
|
||||
pagecontent = self.page.get_content_obj(code)
|
||||
if pagecontent:
|
||||
translation_delete_url = admin_reverse("cms_pagecontent_delete", args=(pagecontent.pk,))
|
||||
url = add_url_parameters(translation_delete_url, language=code)
|
||||
remove_plugins_menu.add_modal_item(name, url=url, disabled=disabled)
|
||||
|
||||
if copy:
|
||||
copy_plugins_menu = language_menu.get_or_create_menu(
|
||||
f"{LANGUAGE_MENU_IDENTIFIER}-copy", _("Copy all plugins")
|
||||
)
|
||||
title = _("from %s")
|
||||
question = _("Are you sure you want to copy all plugins from %s?")
|
||||
|
||||
for code, name in copy:
|
||||
pagecontent = self.page.get_content_obj(code)
|
||||
page_copy_url = admin_reverse("cms_pagecontent_copy_language", args=(pagecontent.pk,))
|
||||
copy_plugins_menu.add_ajax_item(
|
||||
title % name,
|
||||
action=page_copy_url,
|
||||
data={"source_language": code, "target_language": self.current_lang},
|
||||
question=question % name,
|
||||
on_success=self.toolbar.REFRESH_PAGE,
|
||||
)
|
||||
|
||||
def change_admin_menu(self):
|
||||
can_change_page = self.has_page_change_permission()
|
||||
|
||||
if not can_change_page:
|
||||
# Check if the user has permissions to change at least one page
|
||||
can_change_page = page_permissions.user_can_change_at_least_one_page(
|
||||
user=self.request.user,
|
||||
site=self.current_site,
|
||||
)
|
||||
|
||||
if not self._changed_admin_menu and can_change_page:
|
||||
admin_menu = self.toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
|
||||
url = admin_reverse("cms_pagecontent_changelist") # cms page admin
|
||||
params = {"language": self.toolbar.request_language}
|
||||
if self.page:
|
||||
params["page_id"] = self.page.pk
|
||||
url = add_url_parameters(url, params)
|
||||
admin_menu.add_sideframe_item(_("Pages"), url=url, position=0)
|
||||
# Used to prevent duplicates
|
||||
self._changed_admin_menu = True
|
||||
|
||||
def add_page_menu(self):
|
||||
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(
|
||||
user=self.request.user,
|
||||
page=self.page,
|
||||
site=self.current_site,
|
||||
)
|
||||
|
||||
# menu for current page
|
||||
# NOTE: disabled if the current path is "deeper" into the
|
||||
# application's url patterns than its root. This is because
|
||||
# when the Content Manager is at the root of the app-hook,
|
||||
# some of the page options still make sense.
|
||||
current_page_menu = self.toolbar.get_or_create_menu(
|
||||
PAGE_MENU_IDENTIFIER, _("Page"), position=1, disabled=self.in_apphook() and not self.in_apphook_root()
|
||||
)
|
||||
|
||||
new_page_params = {"edit": 1, "site": self.page.site_id}
|
||||
new_sub_page_params = {"edit": 1, "parent_page": self.page.id}
|
||||
|
||||
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.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,
|
||||
site=self.current_site,
|
||||
)
|
||||
|
||||
if self.page.parent:
|
||||
new_page_params["parent_page"] = self.page.parent.id
|
||||
can_add_sibling_page = page_permissions.user_can_add_subpage(
|
||||
user=self.request.user,
|
||||
target=self.page.parent,
|
||||
)
|
||||
else:
|
||||
can_add_sibling_page = can_add_root_page
|
||||
|
||||
can_add_sub_page = page_permissions.user_can_add_subpage(
|
||||
user=self.request.user,
|
||||
target=self.page,
|
||||
)
|
||||
|
||||
# page operations menu
|
||||
add_page_menu = current_page_menu.get_or_create_menu(
|
||||
PAGE_MENU_ADD_IDENTIFIER,
|
||||
_("Create Page"),
|
||||
)
|
||||
|
||||
add_page_menu_modal_items = (
|
||||
(_("New Page"), new_page_params, can_add_sibling_page),
|
||||
(_("New Sub Page"), new_sub_page_params, can_add_sub_page),
|
||||
)
|
||||
|
||||
for title, params, has_perm in add_page_menu_modal_items:
|
||||
params.update(language=self.toolbar.request_language)
|
||||
add_page_menu.add_modal_item(
|
||||
title,
|
||||
url=add_url_parameters(add_page_url, params),
|
||||
disabled=not has_perm,
|
||||
)
|
||||
|
||||
add_page_menu.add_modal_item(
|
||||
_("Duplicate this Page"),
|
||||
url=add_url_parameters(duplicate_page_url, {"language": self.toolbar.request_language}),
|
||||
disabled=not can_add_sibling_page,
|
||||
)
|
||||
|
||||
# first break
|
||||
current_page_menu.add_break(PAGE_MENU_FIRST_BREAK)
|
||||
|
||||
# page settings
|
||||
page_settings_url = add_url_parameters(page_settings_url, language=self.toolbar.request_language)
|
||||
settings_disabled = not can_change
|
||||
current_page_menu.add_modal_item(
|
||||
_("Page settings"), url=page_settings_url, disabled=settings_disabled, on_close=refresh
|
||||
)
|
||||
|
||||
# advanced settings
|
||||
advanced_url = add_url_parameters(advanced_url, language=self.toolbar.request_language)
|
||||
can_change_advanced = self.page.has_advanced_settings_permission(self.request.user)
|
||||
can_change_permissions = get_cms_setting("PERMISSION") and self.page.has_change_permissions_permission(
|
||||
self.request.user
|
||||
)
|
||||
advanced_disabled = not can_change_advanced and not can_change_permissions
|
||||
current_page_menu.add_modal_item(_("Advanced settings"), url=advanced_url, disabled=advanced_disabled)
|
||||
|
||||
# templates menu
|
||||
if edit_mode:
|
||||
action = admin_reverse("cms_pagecontent_change_template", args=(self.page_content.pk,))
|
||||
|
||||
if get_cms_setting("TEMPLATES"):
|
||||
options = self.page_content.template_choices
|
||||
template_menu = _("Templates")
|
||||
else:
|
||||
options = [(placeholders[0], placeholders[2]) for placeholders in get_cms_setting("PLACEHOLDERS")]
|
||||
template_menu = _("Placeholders")
|
||||
if options:
|
||||
templates_menu = current_page_menu.get_or_create_menu(
|
||||
"templates",
|
||||
template_menu,
|
||||
disabled=not can_change,
|
||||
)
|
||||
|
||||
for path, name in options:
|
||||
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.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.page_content.pk,))
|
||||
current_page_menu.add_ajax_item(
|
||||
nav_title,
|
||||
action=nav_action,
|
||||
disabled=(not edit_mode or not can_change),
|
||||
on_success=refresh,
|
||||
)
|
||||
|
||||
# delete
|
||||
delete_url = admin_reverse("cms_page_delete", args=(self.page.pk,))
|
||||
delete_disabled = not edit_mode or not user_can_delete_page(self.request.user, page=self.page)
|
||||
on_delete_redirect_url = self.get_on_delete_redirect_url() if not delete_disabled else None
|
||||
current_page_menu.add_modal_item(
|
||||
_("Delete page"), url=delete_url, on_close=on_delete_redirect_url, disabled=delete_disabled
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue