Initial commit
This commit is contained in:
0
env/lib/python3.10/site-packages/wagtail/admin/ui/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/wagtail/admin/ui/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/components.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/components.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/editing_sessions.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/editing_sessions.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/fields.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/fields.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/side_panels.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/side_panels.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/sidebar.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/__pycache__/sidebar.cpython-310.pyc
vendored
Normal file
Binary file not shown.
2
env/lib/python3.10/site-packages/wagtail/admin/ui/components.py
vendored
Normal file
2
env/lib/python3.10/site-packages/wagtail/admin/ui/components.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Import components from the Laces library which was extracted from Wagtail.
|
||||
from laces.components import Component, MediaContainer # noqa: F401
|
||||
47
env/lib/python3.10/site-packages/wagtail/admin/ui/editing_sessions.py
vendored
Normal file
47
env/lib/python3.10/site-packages/wagtail/admin/ui/editing_sessions.py
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
from django.conf import settings
|
||||
|
||||
from wagtail.admin.ui.components import Component
|
||||
|
||||
|
||||
class EditingSessionsModule(Component):
|
||||
template_name = "wagtailadmin/shared/editing_sessions/module.html"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
current_session,
|
||||
ping_url,
|
||||
release_url,
|
||||
other_sessions,
|
||||
revision_id=None,
|
||||
):
|
||||
self.current_session = current_session
|
||||
self.ping_url = ping_url
|
||||
self.release_url = release_url
|
||||
self.sessions_list = EditingSessionsList(current_session, other_sessions)
|
||||
self.revision_id = revision_id
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
ping_interval = getattr(
|
||||
settings,
|
||||
"WAGTAIL_EDITING_SESSION_PING_INTERVAL",
|
||||
10000,
|
||||
)
|
||||
return {
|
||||
"current_session": self.current_session,
|
||||
"ping_url": self.ping_url,
|
||||
"release_url": self.release_url,
|
||||
"ping_interval": str(ping_interval), # avoid the need to | unlocalize
|
||||
"sessions_list": self.sessions_list,
|
||||
"revision_id": self.revision_id,
|
||||
}
|
||||
|
||||
|
||||
class EditingSessionsList(Component):
|
||||
template_name = "wagtailadmin/shared/editing_sessions/list.html"
|
||||
|
||||
def __init__(self, current_session, other_sessions):
|
||||
self.current_session = current_session
|
||||
self.sessions = other_sessions
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
return {"current_session": self.current_session, "sessions": self.sessions}
|
||||
40
env/lib/python3.10/site-packages/wagtail/admin/ui/fields.py
vendored
Normal file
40
env/lib/python3.10/site-packages/wagtail/admin/ui/fields.py
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import models
|
||||
|
||||
from wagtail.admin.ui.components import Component
|
||||
from wagtail.utils.registry import ModelFieldRegistry
|
||||
|
||||
display_class_registry = ModelFieldRegistry()
|
||||
|
||||
|
||||
def register_display_class(field_class, to=None, display_class=None, exact_class=False):
|
||||
"""
|
||||
Define how model field values should be rendered in the admin.
|
||||
The `display_class` should be a subclass of `wagtail.admin.ui.components.Component`
|
||||
that takes a single argument in its constructor: the value of the field.
|
||||
|
||||
This is mainly useful for defining how fields are rendered in the inspect view,
|
||||
but it can also be used in other places, e.g. listing views.
|
||||
"""
|
||||
|
||||
if display_class is None:
|
||||
raise ImproperlyConfigured(
|
||||
"register_display_class must be passed a 'display_class' keyword argument"
|
||||
)
|
||||
|
||||
if to and field_class != models.ForeignKey:
|
||||
raise ImproperlyConfigured(
|
||||
"The 'to' argument on register_display_class is only valid for ForeignKey fields"
|
||||
)
|
||||
|
||||
display_class_registry.register(
|
||||
field_class, to=to, value=display_class, exact_class=exact_class
|
||||
)
|
||||
|
||||
|
||||
class BaseFieldDisplay(Component):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
return {"value": self.value}
|
||||
357
env/lib/python3.10/site-packages/wagtail/admin/ui/side_panels.py
vendored
Normal file
357
env/lib/python3.10/site-packages/wagtail/admin/ui/side_panels.py
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
from django.urls import reverse
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import gettext_lazy, ngettext
|
||||
|
||||
from wagtail import hooks
|
||||
from wagtail.admin.ui.components import Component
|
||||
from wagtail.admin.userbar import AccessibilityItem
|
||||
from wagtail.models import DraftStateMixin, LockableMixin, Page, ReferenceIndex
|
||||
|
||||
|
||||
class BaseSidePanel(Component):
|
||||
class SidePanelToggle(Component):
|
||||
template_name = "wagtailadmin/shared/side_panel_toggle.html"
|
||||
aria_label = ""
|
||||
icon_name = ""
|
||||
has_counter = True
|
||||
counter_classname = ""
|
||||
keyboard_shortcut = None
|
||||
|
||||
def __init__(self, panel):
|
||||
self.panel = panel
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
# Inherit classes from fragments defined in slim_header.html
|
||||
inherit = {
|
||||
"nav_icon_button_classes",
|
||||
"nav_icon_classes",
|
||||
"nav_icon_counter_classes",
|
||||
}
|
||||
context = {key: parent_context.get(key) for key in inherit}
|
||||
context["toggle"] = self
|
||||
context["panel"] = self.panel
|
||||
context["count"] = 0
|
||||
return context
|
||||
|
||||
def __init__(self, object, request):
|
||||
self.object = object
|
||||
self.request = request
|
||||
self.model = type(self.object)
|
||||
self.toggle = self.SidePanelToggle(panel=self)
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = {"panel": self, "object": self.object, "request": self.request}
|
||||
if issubclass(self.model, Page):
|
||||
context["page"] = self.object
|
||||
return context
|
||||
|
||||
|
||||
class StatusSidePanel(BaseSidePanel):
|
||||
class SidePanelToggle(BaseSidePanel.SidePanelToggle):
|
||||
aria_label = gettext_lazy("Toggle status")
|
||||
icon_name = "info-circle"
|
||||
counter_classname = "w-bg-critical-200"
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
form = parent_context.get("form")
|
||||
context["count"] = form and len(
|
||||
form.errors.keys() & {"go_live_at", "expire_at"}
|
||||
)
|
||||
return context
|
||||
|
||||
name = "status"
|
||||
title = gettext_lazy("Status")
|
||||
template_name = "wagtailadmin/shared/side_panels/status.html"
|
||||
order = 100
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
show_schedule_publishing_toggle=None,
|
||||
live_object=None,
|
||||
scheduled_object=None,
|
||||
locale=None,
|
||||
translations=None,
|
||||
usage_url=None,
|
||||
history_url=None,
|
||||
last_updated_info=None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.show_schedule_publishing_toggle = show_schedule_publishing_toggle
|
||||
self.live_object = live_object
|
||||
self.scheduled_object = scheduled_object
|
||||
self.locale = locale
|
||||
self.translations = translations
|
||||
self.usage_url = usage_url
|
||||
self.history_url = history_url
|
||||
self.last_updated_info = last_updated_info
|
||||
self.locking_enabled = isinstance(self.object, LockableMixin)
|
||||
|
||||
def get_status_templates(self, context):
|
||||
templates = ["wagtailadmin/shared/side_panels/includes/status/workflow.html"]
|
||||
|
||||
if self.locale:
|
||||
templates.append(
|
||||
"wagtailadmin/shared/side_panels/includes/status/locale.html"
|
||||
)
|
||||
|
||||
if self.object.pk:
|
||||
if self.locking_enabled:
|
||||
templates.append(
|
||||
"wagtailadmin/shared/side_panels/includes/status/locked.html"
|
||||
)
|
||||
|
||||
if self.usage_url:
|
||||
templates.append(
|
||||
"wagtailadmin/shared/side_panels/includes/status/usage.html"
|
||||
)
|
||||
|
||||
return templates
|
||||
|
||||
def get_scheduled_publishing_context(self, parent_context):
|
||||
if not isinstance(self.object, DraftStateMixin):
|
||||
return {"draftstate_enabled": False}
|
||||
|
||||
context = {
|
||||
# Used for hiding the info completely if the model doesn't extend DraftStateMixin
|
||||
"draftstate_enabled": True,
|
||||
# Show error message if any of the scheduled publishing fields has errors
|
||||
"schedule_has_errors": False,
|
||||
# The dialog toggle can be hidden (e.g. if PublishingPanel is not present)
|
||||
# but the scheduled publishing info should still be shown
|
||||
"show_schedule_publishing_toggle": self.show_schedule_publishing_toggle,
|
||||
# These are the dates that show up with the unticked calendar icon,
|
||||
# aka "draft schedule"
|
||||
"draft_go_live_at": None,
|
||||
"draft_expire_at": None,
|
||||
# These are the dates that show up with the ticked calendar icon,
|
||||
# aka "active schedule"
|
||||
"scheduled_go_live_at": None,
|
||||
"scheduled_expire_at": None,
|
||||
# This is for an edge case where the live object already has an
|
||||
# expire_at, which can still take effect if the active schedule's
|
||||
# go_live_at is later than that
|
||||
"live_expire_at": None,
|
||||
}
|
||||
|
||||
# Reuse logic from the toggle to get the count of errors
|
||||
if self.toggle.get_context_data(parent_context)["count"]:
|
||||
context["schedule_has_errors"] = True
|
||||
|
||||
# Only consider draft schedule if the object hasn't been created
|
||||
# or if there are unpublished changes
|
||||
if not self.object.pk or self.object.has_unpublished_changes:
|
||||
context["draft_go_live_at"] = self.object.go_live_at
|
||||
context["draft_expire_at"] = self.object.expire_at
|
||||
|
||||
# Get active schedule from the scheduled revision's object (if any)
|
||||
if self.scheduled_object:
|
||||
context["scheduled_go_live_at"] = self.scheduled_object.go_live_at
|
||||
context["scheduled_expire_at"] = self.scheduled_object.expire_at
|
||||
|
||||
# Ignore draft schedule if it's the same as the active schedule
|
||||
if context["draft_go_live_at"] == context["scheduled_go_live_at"]:
|
||||
context["draft_go_live_at"] = None
|
||||
|
||||
if context["draft_expire_at"] == context["scheduled_expire_at"]:
|
||||
context["draft_expire_at"] = None
|
||||
|
||||
# The live object can still have its own active expiry date
|
||||
# that's separate from the active schedule
|
||||
if (
|
||||
self.live_object
|
||||
and self.live_object.expire_at
|
||||
and not self.live_object.expired
|
||||
):
|
||||
context["live_expire_at"] = self.live_object.expire_at
|
||||
|
||||
# Ignore the live object's expiry date if the active schedule has
|
||||
# an earlier go_live_at, as the active schedule's expiry date will
|
||||
# override the live object's expiry date when the draft is published
|
||||
if (
|
||||
context["scheduled_go_live_at"]
|
||||
and context["scheduled_go_live_at"] < context["live_expire_at"]
|
||||
):
|
||||
context["live_expire_at"] = None
|
||||
|
||||
# Only show the box for the live object expire_at edge case
|
||||
# if it passes the checks above
|
||||
context["has_live_publishing_schedule"] = bool(context["live_expire_at"])
|
||||
|
||||
# Only show the main scheduled publishing box if it has at least one of
|
||||
# the draft/active schedule dates after passing the checks above
|
||||
context["has_draft_publishing_schedule"] = any(
|
||||
(
|
||||
context["scheduled_go_live_at"],
|
||||
context["scheduled_expire_at"],
|
||||
context["draft_go_live_at"],
|
||||
context["draft_expire_at"],
|
||||
)
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
def get_lock_context(self, parent_context):
|
||||
self.lock = None
|
||||
lock_context = {}
|
||||
if self.locking_enabled:
|
||||
self.lock = self.object.get_lock()
|
||||
if self.lock:
|
||||
lock_context = self.lock.get_context_for_user(
|
||||
self.request.user, parent_context
|
||||
)
|
||||
return {
|
||||
"lock": self.lock,
|
||||
"user_can_lock": parent_context.get("user_can_lock"),
|
||||
"user_can_unlock": parent_context.get("user_can_unlock"),
|
||||
"lock_context": lock_context,
|
||||
}
|
||||
|
||||
def get_usage_context(self):
|
||||
return {
|
||||
"usage_count": ReferenceIndex.get_grouped_references_to(
|
||||
self.object
|
||||
).count(),
|
||||
"usage_url": self.usage_url,
|
||||
}
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
context["locale"] = self.locale
|
||||
context["translations"] = self.translations
|
||||
if self.translations:
|
||||
context["translations_total"] = len(self.translations) + 1
|
||||
context["model_name"] = capfirst(self.model._meta.verbose_name)
|
||||
context["base_model_name"] = context["model_name"]
|
||||
context["history_url"] = self.history_url
|
||||
context["status_templates"] = self.get_status_templates(context)
|
||||
context["last_updated_info"] = self.last_updated_info
|
||||
context.update(self.get_scheduled_publishing_context(parent_context))
|
||||
context.update(self.get_lock_context(parent_context))
|
||||
if self.object.pk and self.usage_url:
|
||||
context.update(self.get_usage_context())
|
||||
return context
|
||||
|
||||
|
||||
class PageStatusSidePanel(StatusSidePanel):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.object.pk:
|
||||
self.usage_url = reverse("wagtailadmin_pages:usage", args=(self.object.pk,))
|
||||
|
||||
permissions = self.object.permissions_for_user(self.request.user)
|
||||
if permissions.can_view_revisions():
|
||||
self.history_url = reverse(
|
||||
"wagtailadmin_pages:history",
|
||||
args=(self.object.pk,),
|
||||
)
|
||||
|
||||
def get_status_templates(self, context):
|
||||
templates = super().get_status_templates(context)
|
||||
templates.insert(
|
||||
-1, "wagtailadmin/shared/side_panels/includes/status/privacy.html"
|
||||
)
|
||||
return templates
|
||||
|
||||
def get_usage_context(self):
|
||||
context = super().get_usage_context()
|
||||
context["usage_url_text"] = ngettext(
|
||||
"Referenced %(count)s time",
|
||||
"Referenced %(count)s times",
|
||||
context["usage_count"],
|
||||
) % {"count": context["usage_count"]}
|
||||
return context
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
page = self.object
|
||||
|
||||
if page.id:
|
||||
context.update(
|
||||
{
|
||||
"workflow_history_url": reverse(
|
||||
"wagtailadmin_pages:workflow_history", args=(page.id,)
|
||||
),
|
||||
"revisions_compare_url_name": "wagtailadmin_pages:revisions_compare",
|
||||
"lock_url": reverse("wagtailadmin_pages:lock", args=(page.id,)),
|
||||
"unlock_url": reverse("wagtailadmin_pages:unlock", args=(page.id,)),
|
||||
}
|
||||
)
|
||||
|
||||
context.update(
|
||||
{
|
||||
"model_name": self.model.get_verbose_name(),
|
||||
"base_model_name": Page._meta.verbose_name,
|
||||
"model_description": self.model.get_page_description(),
|
||||
"status_templates": self.get_status_templates(context),
|
||||
}
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class CommentsSidePanel(BaseSidePanel):
|
||||
class SidePanelToggle(BaseSidePanel.SidePanelToggle):
|
||||
aria_label = gettext_lazy("Toggle comments")
|
||||
icon_name = "comment"
|
||||
|
||||
name = "comments"
|
||||
title = gettext_lazy("Comments")
|
||||
template_name = "wagtailadmin/shared/side_panels/comments.html"
|
||||
order = 300
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
context["form"] = parent_context.get("form")
|
||||
return context
|
||||
|
||||
|
||||
class ChecksSidePanel(BaseSidePanel):
|
||||
class SidePanelToggle(BaseSidePanel.SidePanelToggle):
|
||||
aria_label = gettext_lazy("Toggle checks")
|
||||
icon_name = "glasses"
|
||||
|
||||
name = "checks"
|
||||
title = gettext_lazy("Checks")
|
||||
template_name = "wagtailadmin/shared/side_panels/checks.html"
|
||||
order = 350
|
||||
|
||||
def get_axe_configuration(self):
|
||||
# Retrieve the Axe configuration from the userbar.
|
||||
userbar_items = [AccessibilityItem()]
|
||||
for fn in hooks.get_hooks("construct_wagtail_userbar"):
|
||||
fn(self.request, userbar_items)
|
||||
|
||||
for item in userbar_items:
|
||||
if isinstance(item, AccessibilityItem):
|
||||
return item.get_axe_configuration(self.request)
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
context["axe_configuration"] = self.get_axe_configuration()
|
||||
return context
|
||||
|
||||
|
||||
class PreviewSidePanel(BaseSidePanel):
|
||||
class SidePanelToggle(BaseSidePanel.SidePanelToggle):
|
||||
aria_label = gettext_lazy("Toggle preview")
|
||||
icon_name = "mobile-alt"
|
||||
has_counter = False
|
||||
keyboard_shortcut = "mod+p"
|
||||
|
||||
name = "preview"
|
||||
title = gettext_lazy("Preview")
|
||||
template_name = "wagtailadmin/shared/side_panels/preview.html"
|
||||
order = 400
|
||||
|
||||
def __init__(self, object, request, *, preview_url):
|
||||
super().__init__(object, request)
|
||||
self.preview_url = preview_url
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
context["preview_url"] = self.preview_url
|
||||
context["has_multiple_modes"] = len(self.object.preview_modes) > 1
|
||||
return context
|
||||
286
env/lib/python3.10/site-packages/wagtail/admin/ui/sidebar.py
vendored
Normal file
286
env/lib/python3.10/site-packages/wagtail/admin/ui/sidebar.py
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
from typing import Any, List, Mapping
|
||||
from warnings import warn
|
||||
|
||||
from django import forms
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from wagtail.admin.staticfiles import versioned_static
|
||||
from wagtail.telepath import Adapter, adapter
|
||||
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
||||
|
||||
|
||||
class BaseSidebarAdapter(Adapter):
|
||||
@cached_property
|
||||
def media(self):
|
||||
return forms.Media(
|
||||
js=[
|
||||
versioned_static("wagtailadmin/js/sidebar.js"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# Main menu
|
||||
|
||||
|
||||
class MenuItem:
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
label: str,
|
||||
icon_name: str = "",
|
||||
classname: str = "",
|
||||
classnames: str = "",
|
||||
attrs: Mapping[str, Any] = None,
|
||||
):
|
||||
if classnames:
|
||||
warn(
|
||||
"The `classnames` kwarg for sidebar MenuItem is deprecated - use `classname` instead.",
|
||||
category=RemovedInWagtail70Warning,
|
||||
)
|
||||
self.name = name
|
||||
self.label = label
|
||||
self.icon_name = icon_name
|
||||
self.classname = classname or classnames
|
||||
self.attrs = attrs or {}
|
||||
|
||||
def js_args(self):
|
||||
return [
|
||||
{
|
||||
"name": self.name,
|
||||
"label": self.label,
|
||||
"icon_name": self.icon_name,
|
||||
"classname": self.classname,
|
||||
"attrs": self.attrs,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.LinkMenuItem", base=BaseSidebarAdapter)
|
||||
class LinkMenuItem(MenuItem):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
label: str,
|
||||
url: str,
|
||||
icon_name: str = "",
|
||||
classname: str = "",
|
||||
classnames: str = "",
|
||||
attrs: Mapping[str, Any] = None,
|
||||
):
|
||||
if classnames:
|
||||
warn(
|
||||
"The `classnames` kwarg for sidebar LinkMenuItem is deprecated - use `classname` instead.",
|
||||
category=RemovedInWagtail70Warning,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
label,
|
||||
icon_name=icon_name,
|
||||
classname=classname or classnames,
|
||||
attrs=attrs,
|
||||
)
|
||||
self.url = url
|
||||
|
||||
def js_args(self):
|
||||
args = super().js_args()
|
||||
args[0]["url"] = self.url
|
||||
return args
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
self.__class__ == other.__class__
|
||||
and self.name == other.name
|
||||
and self.label == other.label
|
||||
and self.url == other.url
|
||||
and self.icon_name == other.icon_name
|
||||
and self.classname == other.classname
|
||||
and self.attrs == other.attrs
|
||||
)
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.ActionMenuItem", base=BaseSidebarAdapter)
|
||||
class ActionMenuItem(MenuItem):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
label: str,
|
||||
action: str,
|
||||
icon_name: str = "",
|
||||
classname: str = "",
|
||||
classnames: str = "",
|
||||
method: str = "POST",
|
||||
attrs: Mapping[str, Any] = None,
|
||||
):
|
||||
if classnames:
|
||||
warn(
|
||||
"The `classnames` kwarg for sidebar ActionMenuItem is deprecated - use `classname` instead.",
|
||||
category=RemovedInWagtail70Warning,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
label,
|
||||
icon_name=icon_name,
|
||||
classname=classname or classnames,
|
||||
attrs=attrs,
|
||||
)
|
||||
self.action = action
|
||||
self.method = method
|
||||
|
||||
def js_args(self):
|
||||
args = super().js_args()
|
||||
args[0]["action"] = self.action
|
||||
args[0]["method"] = self.method
|
||||
return args
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
self.__class__ == other.__class__
|
||||
and self.name == other.name
|
||||
and self.label == other.label
|
||||
and self.action == other.action
|
||||
and self.method == other.method
|
||||
and self.icon_name == other.icon_name
|
||||
and self.classname == other.classname
|
||||
and self.attrs == other.attrs
|
||||
)
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.SubMenuItem", base=BaseSidebarAdapter)
|
||||
class SubMenuItem(MenuItem):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
label: str,
|
||||
menu_items: List[MenuItem],
|
||||
icon_name: str = "",
|
||||
classname: str = "",
|
||||
classnames: str = "",
|
||||
footer_text: str = "",
|
||||
attrs: Mapping[str, Any] = None,
|
||||
):
|
||||
if classnames:
|
||||
warn(
|
||||
"The `classnames` kwarg for sidebar SubMenuItem is deprecated - use `classname` instead.",
|
||||
category=RemovedInWagtail70Warning,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
label,
|
||||
icon_name=icon_name,
|
||||
classname=classname or classnames,
|
||||
attrs=attrs,
|
||||
)
|
||||
self.menu_items = menu_items
|
||||
self.footer_text = footer_text
|
||||
|
||||
def js_args(self):
|
||||
args = super().js_args()
|
||||
args[0]["footer_text"] = self.footer_text
|
||||
args.append(self.menu_items)
|
||||
return args
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
self.__class__ == other.__class__
|
||||
and self.name == other.name
|
||||
and self.label == other.label
|
||||
and self.menu_items == other.menu_items
|
||||
and self.icon_name == other.icon_name
|
||||
and self.classname == other.classname
|
||||
and self.footer_text == other.footer_text
|
||||
and self.attrs == other.attrs
|
||||
)
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.PageExplorerMenuItem", base=BaseSidebarAdapter)
|
||||
class PageExplorerMenuItem(LinkMenuItem):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
label: str,
|
||||
url: str,
|
||||
start_page_id: int,
|
||||
icon_name: str = "",
|
||||
classname: str = "",
|
||||
classnames: str = "",
|
||||
attrs: Mapping[str, Any] = None,
|
||||
):
|
||||
if classnames:
|
||||
warn(
|
||||
"The `classnames` kwarg for sidebar PageExplorerMenuItem is deprecated - use `classname` instead.",
|
||||
category=RemovedInWagtail70Warning,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
label,
|
||||
url,
|
||||
icon_name=icon_name,
|
||||
classname=classname or classnames,
|
||||
attrs=attrs,
|
||||
)
|
||||
self.start_page_id = start_page_id
|
||||
|
||||
def js_args(self):
|
||||
args = super().js_args()
|
||||
args.append(self.start_page_id)
|
||||
return args
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
self.__class__ == other.__class__
|
||||
and self.name == other.name
|
||||
and self.label == other.label
|
||||
and self.url == other.url
|
||||
and self.start_page_id == other.start_page_id
|
||||
and self.icon_name == other.icon_name
|
||||
and self.classname == other.classname
|
||||
and self.attrs == other.attrs
|
||||
)
|
||||
|
||||
|
||||
# Modules
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.WagtailBrandingModule", base=BaseSidebarAdapter)
|
||||
class WagtailBrandingModule:
|
||||
def js_args(self):
|
||||
return [
|
||||
reverse("wagtailadmin_home"),
|
||||
]
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.SearchModule", base=BaseSidebarAdapter)
|
||||
class SearchModule:
|
||||
def __init__(self, search_area):
|
||||
self.search_area = search_area
|
||||
|
||||
def js_args(self):
|
||||
return [self.search_area.url]
|
||||
|
||||
|
||||
@adapter("wagtail.sidebar.MainMenuModule", base=BaseSidebarAdapter)
|
||||
class MainMenuModule:
|
||||
def __init__(
|
||||
self, menu_items: List[MenuItem], account_menu_items: List[MenuItem], user
|
||||
):
|
||||
self.menu_items = menu_items
|
||||
self.account_menu_items = account_menu_items
|
||||
self.user = user
|
||||
|
||||
def js_args(self):
|
||||
from wagtail.admin.templatetags.wagtailadmin_tags import avatar_url
|
||||
|
||||
try:
|
||||
first_name = self.user.first_name
|
||||
except AttributeError:
|
||||
first_name = None
|
||||
|
||||
return [
|
||||
self.menu_items,
|
||||
self.account_menu_items,
|
||||
{
|
||||
"name": first_name or self.user.get_username(),
|
||||
"avatarUrl": avatar_url(self.user, size=50),
|
||||
},
|
||||
]
|
||||
520
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/__init__.py
vendored
Normal file
520
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/__init__.py
vendored
Normal file
@@ -0,0 +1,520 @@
|
||||
"""Helper classes for formatting data as tables"""
|
||||
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Mapping
|
||||
|
||||
from django.contrib.admin.utils import quote
|
||||
from django.forms import MediaDefiningClass
|
||||
from django.template.loader import get_template
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import gettext, gettext_lazy
|
||||
|
||||
from wagtail.admin.ui.components import Component
|
||||
from wagtail.coreutils import multigetattr
|
||||
|
||||
|
||||
class BaseColumn(metaclass=MediaDefiningClass):
|
||||
class Header:
|
||||
# Helper object used for rendering column headers in templates -
|
||||
# behaves as a component (i.e. it has a render_html method) but delegates rendering
|
||||
# to Column.render_header_html
|
||||
def __init__(self, column):
|
||||
self.column = column
|
||||
|
||||
def render_html(self, parent_context):
|
||||
return self.column.render_header_html(parent_context)
|
||||
|
||||
class Cell:
|
||||
# Helper object used for rendering table cells in templates -
|
||||
# behaves as a component (i.e. it has a render_html method) but delegates rendering
|
||||
# to Column.render_cell_html
|
||||
def __init__(self, column, instance):
|
||||
self.column = column
|
||||
self.instance = instance
|
||||
|
||||
def render_html(self, parent_context):
|
||||
return self.column.render_cell_html(self.instance, parent_context)
|
||||
|
||||
header_template_name = "wagtailadmin/tables/column_header.html"
|
||||
cell_template_name = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
label=None,
|
||||
accessor=None,
|
||||
classname=None,
|
||||
sort_key=None,
|
||||
width=None,
|
||||
ascending_title_text=None,
|
||||
descending_title_text=None,
|
||||
):
|
||||
self.name = name
|
||||
self.accessor = accessor or name
|
||||
if label is None:
|
||||
self.label = capfirst(name.replace("_", " "))
|
||||
else:
|
||||
self.label = label
|
||||
self.classname = classname
|
||||
self.sort_key = sort_key
|
||||
self.header = Column.Header(self)
|
||||
self.width = width
|
||||
self.ascending_title_text = ascending_title_text
|
||||
self.descending_title_text = descending_title_text
|
||||
|
||||
def get_header_context_data(self, parent_context):
|
||||
"""
|
||||
Compiles the context dictionary to pass to the header template when rendering the column header
|
||||
"""
|
||||
table = parent_context["table"]
|
||||
return {
|
||||
"column": self,
|
||||
"table": table,
|
||||
"is_orderable": bool(self.sort_key),
|
||||
"is_ascending": self.sort_key and table.ordering == self.sort_key,
|
||||
"is_descending": self.sort_key and table.ordering == ("-" + self.sort_key),
|
||||
"request": parent_context.get("request"),
|
||||
"ascending_title_text": self.ascending_title_text
|
||||
or table.get_ascending_title_text(self),
|
||||
"descending_title_text": self.descending_title_text
|
||||
or table.get_descending_title_text(self),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def header_template(self):
|
||||
return get_template(self.header_template_name)
|
||||
|
||||
@cached_property
|
||||
def cell_template(self):
|
||||
if self.cell_template_name is None:
|
||||
raise NotImplementedError(
|
||||
"cell_template_name must be specified on %r" % self
|
||||
)
|
||||
return get_template(self.cell_template_name)
|
||||
|
||||
def render_header_html(self, parent_context):
|
||||
"""
|
||||
Renders the column's header
|
||||
"""
|
||||
context = self.get_header_context_data(parent_context)
|
||||
return self.header_template.render(context)
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
"""
|
||||
Compiles the context dictionary to pass to the cell template when rendering a table cell for
|
||||
the given instance
|
||||
"""
|
||||
return {
|
||||
"instance": instance,
|
||||
"column": self,
|
||||
"row": parent_context["row"],
|
||||
"table": parent_context["table"],
|
||||
"request": parent_context.get("request"),
|
||||
}
|
||||
|
||||
def render_cell_html(self, instance, parent_context):
|
||||
"""
|
||||
Renders a table cell containing data for the given instance
|
||||
"""
|
||||
context = self.get_cell_context_data(instance, parent_context)
|
||||
return self.cell_template.render(context)
|
||||
|
||||
def get_cell(self, instance):
|
||||
"""
|
||||
Return an object encapsulating this column and an item of data, which we can use for
|
||||
rendering a table cell into a template
|
||||
"""
|
||||
return Column.Cell(self, instance)
|
||||
|
||||
def __repr__(self):
|
||||
return "<{}.{}: {}>".format(
|
||||
self.__class__.__module__,
|
||||
self.__class__.__qualname__,
|
||||
self.name,
|
||||
)
|
||||
|
||||
|
||||
class Column(BaseColumn):
|
||||
"""A column that displays a single field of data from the model"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/cell.html"
|
||||
|
||||
def get_value(self, instance):
|
||||
"""
|
||||
Given an instance (i.e. any object containing data), extract the field of data to be
|
||||
displayed in a cell of this column
|
||||
"""
|
||||
if callable(self.accessor):
|
||||
return self.accessor(instance)
|
||||
else:
|
||||
try:
|
||||
return multigetattr(instance, self.accessor)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["value"] = self.get_value(instance)
|
||||
return context
|
||||
|
||||
|
||||
class ButtonsColumnMixin:
|
||||
"""A mixin for columns that contain buttons"""
|
||||
|
||||
buttons = []
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["buttons"] = sorted(self.get_buttons(instance, parent_context))
|
||||
return context
|
||||
|
||||
def get_buttons(self, instance, parent_context):
|
||||
return self.buttons
|
||||
|
||||
|
||||
class TitleColumn(Column):
|
||||
"""A column where data is styled as a title and wrapped in a link or <label>"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/title_cell.html"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
url_name=None,
|
||||
get_url=None,
|
||||
get_title_id=None,
|
||||
label_prefix=None,
|
||||
get_label_id=None,
|
||||
link_classname=None,
|
||||
link_attrs=None,
|
||||
id_accessor="pk",
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(name, **kwargs)
|
||||
self.url_name = url_name
|
||||
self._get_url_func = get_url
|
||||
self._get_title_id_func = get_title_id
|
||||
self.label_prefix = label_prefix
|
||||
self._get_label_id_func = get_label_id
|
||||
self.link_attrs = link_attrs or {}
|
||||
self.link_classname = link_classname
|
||||
self.id_accessor = id_accessor
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["link_attrs"] = self.get_link_attrs(instance, parent_context)
|
||||
context["link_attrs"]["href"] = context["link_url"] = self.get_link_url(
|
||||
instance, parent_context
|
||||
)
|
||||
if self.link_classname is not None:
|
||||
context["link_attrs"]["class"] = self.link_classname
|
||||
context["title_id"] = self.get_title_id(instance, parent_context)
|
||||
context["label_id"] = self.get_label_id(instance, parent_context)
|
||||
return context
|
||||
|
||||
def get_link_attrs(self, instance, parent_context):
|
||||
return self.link_attrs.copy()
|
||||
|
||||
def get_link_url(self, instance, parent_context):
|
||||
if self._get_url_func:
|
||||
return self._get_url_func(instance)
|
||||
elif self.url_name:
|
||||
id = multigetattr(instance, self.id_accessor)
|
||||
return reverse(self.url_name, args=(quote(id),))
|
||||
|
||||
def get_title_id(self, instance, parent_context):
|
||||
if self._get_title_id_func:
|
||||
return self._get_title_id_func(instance)
|
||||
|
||||
def get_label_id(self, instance, parent_context):
|
||||
if self._get_label_id_func:
|
||||
return self._get_label_id_func(instance)
|
||||
elif self.label_prefix:
|
||||
id = multigetattr(instance, self.id_accessor)
|
||||
return f"{self.label_prefix}-{id}"
|
||||
|
||||
|
||||
class StatusFlagColumn(Column):
|
||||
"""Represents a boolean value as a status tag (or lack thereof, if the corresponding label is None)"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/status_flag_cell.html"
|
||||
|
||||
def __init__(self, name, true_label=None, false_label=None, **kwargs):
|
||||
super().__init__(name, **kwargs)
|
||||
self.true_label = true_label
|
||||
self.false_label = false_label
|
||||
|
||||
|
||||
class StatusTagColumn(Column):
|
||||
"""Represents a status tag"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/status_tag_cell.html"
|
||||
|
||||
def __init__(self, name, primary=None, **kwargs):
|
||||
super().__init__(name, **kwargs)
|
||||
self.primary = primary
|
||||
|
||||
def get_primary(self, instance):
|
||||
if callable(self.primary):
|
||||
return self.primary(instance)
|
||||
return self.primary
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["primary"] = self.get_primary(instance)
|
||||
return context
|
||||
|
||||
|
||||
class BooleanColumn(Column):
|
||||
"""Represents a True/False/None value as a tick/cross/question icon"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/boolean_cell.html"
|
||||
|
||||
|
||||
class LiveStatusTagColumn(StatusTagColumn):
|
||||
"""Represents a live/draft status tag"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
"status_string",
|
||||
label=kwargs.pop("label", gettext("Status")),
|
||||
sort_key=kwargs.pop("sort_key", "live"),
|
||||
primary=lambda instance: instance.live,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
class DateColumn(Column):
|
||||
"""Outputs a date in human-readable format"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/date_cell.html"
|
||||
|
||||
|
||||
class UpdatedAtColumn(DateColumn):
|
||||
"""Outputs the _updated_at date annotation in human-readable format"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
"_updated_at",
|
||||
label=kwargs.pop("label", gettext("Updated")),
|
||||
sort_key=kwargs.pop("sort_key", "_updated_at"),
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
||||
class UserColumn(Column):
|
||||
"""Outputs the username and avatar for a user"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/user_cell.html"
|
||||
|
||||
def __init__(self, name, blank_display_name="", **kwargs):
|
||||
super().__init__(name, **kwargs)
|
||||
self.blank_display_name = blank_display_name
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
|
||||
user = context["value"]
|
||||
if user:
|
||||
try:
|
||||
full_name = user.get_full_name().strip()
|
||||
except AttributeError:
|
||||
full_name = ""
|
||||
context["display_name"] = full_name or user.get_username()
|
||||
else:
|
||||
context["display_name"] = self.blank_display_name
|
||||
return context
|
||||
|
||||
|
||||
class BulkActionsCheckboxColumn(BaseColumn):
|
||||
"""
|
||||
A checkbox column for the bulk actions feature.
|
||||
|
||||
When using this column, there should be another column (e.g. a TitleColumn)
|
||||
that has an element with the id "{obj_type}_{instance.pk}_title" that contains
|
||||
the title of the object (and nothing else) for screen reader purposes.
|
||||
"""
|
||||
|
||||
header_template_name = "wagtailadmin/bulk_actions/select_all_checkbox_cell.html"
|
||||
cell_template_name = "wagtailadmin/bulk_actions/listing_checkbox_cell.html"
|
||||
|
||||
def __init__(self, *args, obj_type, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.obj_type = obj_type
|
||||
|
||||
def get_aria_describedby(self, instance):
|
||||
return f"{self.obj_type}_{quote(instance.pk)}_title"
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context.update(
|
||||
{
|
||||
"obj_type": self.obj_type,
|
||||
"aria_describedby": self.get_aria_describedby(instance),
|
||||
}
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class ReferencesColumn(Column):
|
||||
cell_template_name = "wagtailadmin/tables/references_cell.html"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name,
|
||||
label=None,
|
||||
accessor=None,
|
||||
classname=None,
|
||||
sort_key=None,
|
||||
width=None,
|
||||
get_url=None,
|
||||
describe_on_delete=False,
|
||||
):
|
||||
super().__init__(name, label, accessor, classname, sort_key, width)
|
||||
self._get_url_func = get_url
|
||||
self.describe_on_delete = describe_on_delete
|
||||
|
||||
def get_edit_url(self, instance):
|
||||
if self._get_url_func:
|
||||
return self._get_url_func(instance)
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["edit_url"] = self.get_edit_url(instance)
|
||||
context["describe_on_delete"] = self.describe_on_delete
|
||||
return context
|
||||
|
||||
|
||||
class DownloadColumn(Column):
|
||||
cell_template_name = "wagtailadmin/tables/download_cell.html"
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["download_url"] = instance.url
|
||||
return context
|
||||
|
||||
|
||||
class RelatedObjectsColumn(Column):
|
||||
"""Outputs a list of objects related to the object through a one-to-many relationship"""
|
||||
|
||||
cell_template_name = "wagtailadmin/tables/related_objects_cell.html"
|
||||
|
||||
def get_value(self, instance):
|
||||
return getattr(instance, self.accessor).all()
|
||||
|
||||
|
||||
class Table(Component):
|
||||
template_name = "wagtailadmin/tables/table.html"
|
||||
classname = "listing"
|
||||
header_row_classname = ""
|
||||
ascending_title_text_format = gettext_lazy(
|
||||
"Sort by '%(label)s' in ascending order."
|
||||
)
|
||||
descending_title_text_format = gettext_lazy(
|
||||
"Sort by '%(label)s' in descending order."
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
columns,
|
||||
data,
|
||||
template_name=None,
|
||||
base_url=None,
|
||||
ordering=None,
|
||||
classname=None,
|
||||
attrs=None,
|
||||
caption=None,
|
||||
):
|
||||
self.columns = OrderedDict([(column.name, column) for column in columns])
|
||||
self.caption = caption
|
||||
self.data = data
|
||||
if template_name:
|
||||
self.template_name = template_name
|
||||
self.base_url = base_url
|
||||
self.ordering = ordering
|
||||
if classname is not None:
|
||||
self.classname = classname
|
||||
self.base_attrs = attrs or {}
|
||||
|
||||
def get_caption(self):
|
||||
return self.caption
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
context["table"] = self
|
||||
context["request"] = parent_context.get("request")
|
||||
return context
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
media = super().media
|
||||
for col in self.columns.values():
|
||||
media += col.media
|
||||
return media
|
||||
|
||||
@property
|
||||
def rows(self):
|
||||
for index, instance in enumerate(self.data):
|
||||
yield Table.Row(self, instance, index)
|
||||
|
||||
@property
|
||||
def row_count(self):
|
||||
return len(self.data)
|
||||
|
||||
@property
|
||||
def attrs(self):
|
||||
attrs = self.base_attrs.copy()
|
||||
attrs["class"] = self.classname
|
||||
return attrs
|
||||
|
||||
def get_row_classname(self, instance):
|
||||
return ""
|
||||
|
||||
def get_row_attrs(self, instance):
|
||||
attrs = {}
|
||||
classname = self.get_row_classname(instance)
|
||||
if classname:
|
||||
attrs["class"] = classname
|
||||
return attrs
|
||||
|
||||
def has_column_widths(self):
|
||||
return any(column.width for column in self.columns.values())
|
||||
|
||||
def get_ascending_title_text(self, column):
|
||||
if self.ascending_title_text_format:
|
||||
return self.ascending_title_text_format % {"label": column.label}
|
||||
|
||||
def get_descending_title_text(self, column):
|
||||
if self.descending_title_text_format:
|
||||
return self.descending_title_text_format % {"label": column.label}
|
||||
|
||||
class Row(Mapping):
|
||||
# behaves as an OrderedDict whose items are the rendered results of
|
||||
# the corresponding column's format_cell method applied to the instance
|
||||
def __init__(self, table, instance, index):
|
||||
self.table = table
|
||||
self.columns = table.columns
|
||||
self.instance = instance
|
||||
self.index = index
|
||||
|
||||
def __len__(self):
|
||||
return len(self.columns)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.columns[key].get_cell(self.instance)
|
||||
|
||||
def __iter__(self):
|
||||
yield from self.columns
|
||||
|
||||
def __repr__(self):
|
||||
return repr([col.get_cell(self.instance) for col in self.columns.values()])
|
||||
|
||||
@cached_property
|
||||
def classname(self):
|
||||
return self.table.get_row_classname(self.instance)
|
||||
|
||||
@cached_property
|
||||
def attrs(self):
|
||||
return self.table.get_row_attrs(self.instance)
|
||||
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/__pycache__/pages.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/__pycache__/pages.cpython-310.pyc
vendored
Normal file
Binary file not shown.
174
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/pages.py
vendored
Normal file
174
env/lib/python3.10/site-packages/wagtail/admin/ui/tables/pages.py
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext
|
||||
|
||||
from wagtail.admin.ui.tables import BaseColumn, BulkActionsCheckboxColumn, Column, Table
|
||||
|
||||
|
||||
class PageTitleColumn(BaseColumn):
|
||||
header_template_name = "wagtailadmin/pages/listing/_page_title_column_header.html"
|
||||
cell_template_name = "wagtailadmin/pages/listing/_page_title_cell.html"
|
||||
classname = "title"
|
||||
|
||||
def get_header_context_data(self, parent_context):
|
||||
context = super().get_header_context_data(parent_context)
|
||||
parent_page = parent_context.get("parent_page")
|
||||
|
||||
context["items_count"] = parent_context.get("items_count")
|
||||
context["page_obj"] = parent_context.get("page_obj")
|
||||
context["parent_page"] = parent_page
|
||||
|
||||
if parent_page and (
|
||||
parent_context.get("is_searching") or parent_context.get("is_filtering")
|
||||
):
|
||||
# Results are switchable between searching the whole tree and searching just this parent.
|
||||
# Add extra signposting to show which scope we're in, and provide a link to switch scope.
|
||||
if parent_context.get("is_searching_whole_tree"):
|
||||
context["result_scope"] = "whole_tree"
|
||||
else:
|
||||
context["result_scope"] = "parent"
|
||||
else:
|
||||
# No signposting needed
|
||||
context["result_scope"] = None
|
||||
|
||||
# If results are not paginated e.g. when using the OrderingColumn,
|
||||
# all items are displayed on the page
|
||||
context["start_index"] = 1
|
||||
context["end_index"] = context["items_count"]
|
||||
if context["page_obj"]:
|
||||
context["start_index"] = context["page_obj"].start_index()
|
||||
context["end_index"] = context["page_obj"].end_index()
|
||||
|
||||
return context
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["page_perms"] = instance.permissions_for_user(
|
||||
parent_context["request"].user
|
||||
)
|
||||
context["parent_page"] = getattr(instance, "annotated_parent_page", None)
|
||||
context["show_locale_labels"] = parent_context.get("show_locale_labels")
|
||||
context["perms"] = parent_context.get("perms")
|
||||
context["actions_next_url"] = parent_context.get("actions_next_url")
|
||||
return context
|
||||
|
||||
|
||||
class ParentPageColumn(Column):
|
||||
cell_template_name = "wagtailadmin/pages/listing/_parent_page_cell.html"
|
||||
|
||||
def get_value(self, instance):
|
||||
return instance.get_parent()
|
||||
|
||||
|
||||
class PageStatusColumn(BaseColumn):
|
||||
cell_template_name = "wagtailadmin/pages/listing/_page_status_cell.html"
|
||||
|
||||
|
||||
class BulkActionsColumn(BulkActionsCheckboxColumn):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs, obj_type="page")
|
||||
|
||||
def get_header_context_data(self, parent_context):
|
||||
context = super().get_header_context_data(parent_context)
|
||||
parent_page = parent_context.get("parent_page")
|
||||
if parent_page:
|
||||
context["parent"] = parent_page.id
|
||||
return context
|
||||
|
||||
|
||||
class OrderingColumn(BaseColumn):
|
||||
header_template_name = "wagtailadmin/pages/listing/_ordering_header.html"
|
||||
cell_template_name = "wagtailadmin/pages/listing/_ordering_cell.html"
|
||||
|
||||
|
||||
class NavigateToChildrenColumn(BaseColumn):
|
||||
cell_template_name = "wagtailadmin/pages/listing/_navigation_explore.html"
|
||||
|
||||
def get_cell_context_data(self, instance, parent_context):
|
||||
context = super().get_cell_context_data(instance, parent_context)
|
||||
context["page"] = instance
|
||||
context["page_perms"] = instance.permissions_for_user(
|
||||
parent_context["request"].user
|
||||
)
|
||||
return context
|
||||
|
||||
def render_header_html(self, parent_context):
|
||||
return mark_safe("<th></th>")
|
||||
|
||||
|
||||
class PageTable(Table):
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
use_row_ordering_attributes=False,
|
||||
parent_page=None,
|
||||
show_locale_labels=False,
|
||||
actions_next_url=None,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# If true, attributes will be added on the <tr> element to support reordering
|
||||
self.use_row_ordering_attributes = use_row_ordering_attributes
|
||||
|
||||
# The parent page of the pages being listed - used to add extra context to the title text
|
||||
# of the reordering links. Leave this undefined if the pages being listed do not share a
|
||||
# common parent.
|
||||
self.parent_page = parent_page
|
||||
if self.parent_page:
|
||||
# Use more detailed title text that mentions the parent page, if we have one and the
|
||||
# current strings have not been overridden from Table's default
|
||||
if self.ascending_title_text_format == Table.ascending_title_text_format:
|
||||
self.ascending_title_text_format = gettext(
|
||||
"Sort the order of child pages within '%(parent)s' by '%(label)s' in ascending order."
|
||||
)
|
||||
if self.descending_title_text_format == Table.descending_title_text_format:
|
||||
self.descending_title_text_format = gettext(
|
||||
"Sort the order of child pages within '%(parent)s' by '%(label)s' in descending order."
|
||||
)
|
||||
|
||||
self.show_locale_labels = show_locale_labels
|
||||
self.actions_next_url = actions_next_url
|
||||
|
||||
def get_ascending_title_text(self, column):
|
||||
return self.ascending_title_text_format % {
|
||||
"parent": self.parent_page and self.parent_page.get_admin_display_title(),
|
||||
"label": column.label,
|
||||
}
|
||||
|
||||
def get_descending_title_text(self, column):
|
||||
return self.descending_title_text_format % {
|
||||
"parent": self.parent_page and self.parent_page.get_admin_display_title(),
|
||||
"label": column.label,
|
||||
}
|
||||
|
||||
def get_row_classname(self, instance):
|
||||
if not instance.live:
|
||||
return "unpublished"
|
||||
else:
|
||||
return ""
|
||||
|
||||
def get_row_attrs(self, instance):
|
||||
attrs = super().get_row_attrs(instance)
|
||||
if self.use_row_ordering_attributes:
|
||||
attrs["id"] = "page_%d" % instance.id
|
||||
attrs["data-w-orderable-item-id"] = instance.id
|
||||
attrs["data-w-orderable-item-label"] = instance.get_admin_display_title()
|
||||
attrs["data-w-orderable-target"] = "item"
|
||||
return attrs
|
||||
|
||||
def get_context_data(self, parent_context):
|
||||
context = super().get_context_data(parent_context)
|
||||
context["show_locale_labels"] = self.show_locale_labels
|
||||
context["perms"] = parent_context.get("perms")
|
||||
context["items_count"] = parent_context.get("items_count")
|
||||
context["page_obj"] = parent_context.get("page_obj")
|
||||
context["parent_page"] = parent_context.get("parent_page")
|
||||
context["is_searching"] = parent_context.get("is_searching")
|
||||
context["is_filtering"] = parent_context.get("is_filtering")
|
||||
context["is_searching_whole_tree"] = parent_context.get(
|
||||
"is_searching_whole_tree"
|
||||
)
|
||||
context["actions_next_url"] = (
|
||||
self.actions_next_url or parent_context.get("request").path
|
||||
)
|
||||
return context
|
||||
Reference in New Issue
Block a user