12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172 |
- from django.conf import settings
- from django.contrib.auth.models import Permission
- from django.urls import reverse
- from django.utils.http import urlencode
- from django.utils.translation import gettext
- from django.utils.translation import gettext_lazy as _
- from draftjs_exporter.dom import DOM
- import wagtail.admin.rich_text.editors.draftail.features as draftail_features
- from wagtail import __version__, hooks
- from wagtail.admin.admin_url_finder import (
- ModelAdminURLFinder,
- register_admin_url_finder,
- )
- from wagtail.admin.auth import user_has_any_page_permission
- from wagtail.admin.forms.collections import GroupCollectionManagementPermissionFormSet
- from wagtail.admin.menu import MenuItem, SubmenuMenuItem, reports_menu, settings_menu
- from wagtail.admin.navigation import get_explorable_root_page
- from wagtail.admin.rich_text.converters.contentstate import link_entity
- from wagtail.admin.rich_text.converters.editor_html import (
- LinkTypeRule,
- PageLinkHandler,
- WhitelistRule,
- )
- from wagtail.admin.rich_text.converters.html_to_contentstate import (
- BlockElementHandler,
- ExternalLinkElementHandler,
- HorizontalRuleHandler,
- InlineStyleElementHandler,
- ListElementHandler,
- ListItemElementHandler,
- PageLinkElementHandler,
- )
- from wagtail.admin.search import SearchArea
- from wagtail.admin.site_summary import PagesSummaryItem
- from wagtail.admin.ui.sidebar import (
- PageExplorerMenuItem as PageExplorerMenuItemComponent,
- )
- from wagtail.admin.ui.sidebar import SubMenuItem as SubMenuItemComponent
- from wagtail.admin.views.pages.bulk_actions import (
- DeleteBulkAction,
- MoveBulkAction,
- PublishBulkAction,
- UnpublishBulkAction,
- )
- from wagtail.admin.viewsets import viewsets
- from wagtail.admin.widgets import Button, ButtonWithDropdownFromHook, PageListingButton
- from wagtail.models import (
- Collection,
- Locale,
- Page,
- Task,
- UserPagePermissionsProxy,
- Workflow,
- )
- from wagtail.permissions import (
- collection_permission_policy,
- task_permission_policy,
- workflow_permission_policy,
- )
- from wagtail.whitelist import allow_without_attributes, attribute_rule, check_url
- class ExplorerMenuItem(MenuItem):
- def is_shown(self, request):
- return user_has_any_page_permission(request.user)
- def get_context(self, request):
- context = super().get_context(request)
- start_page = get_explorable_root_page(request.user)
- if start_page:
- context["start_page_id"] = start_page.id
- return context
- def render_component(self, request):
- start_page = get_explorable_root_page(request.user)
- if start_page:
- return PageExplorerMenuItemComponent(
- self.name,
- self.label,
- self.url,
- start_page.id,
- icon_name=self.icon_name,
- classnames=self.classnames,
- )
- else:
- return super().render_component(request)
- @hooks.register("register_admin_menu_item")
- def register_explorer_menu_item():
- return ExplorerMenuItem(
- _("Pages"),
- reverse("wagtailadmin_explore_root"),
- name="explorer",
- icon_name="folder-open-inverse",
- order=100,
- )
- class SettingsMenuItem(SubmenuMenuItem):
- def render_component(self, request):
- return SubMenuItemComponent(
- self.name,
- self.label,
- self.menu.render_component(request),
- icon_name=self.icon_name,
- classnames=self.classnames,
- footer_text="Wagtail v." + __version__,
- )
- @hooks.register("register_admin_menu_item")
- def register_settings_menu():
- return SettingsMenuItem(_("Settings"), settings_menu, icon_name="cogs", order=10000)
- @hooks.register("register_permissions")
- def register_permissions():
- return Permission.objects.filter(
- content_type__app_label="wagtailadmin", codename="access_admin"
- )
- class PageSearchArea(SearchArea):
- def __init__(self):
- super().__init__(
- _("Pages"),
- reverse("wagtailadmin_pages:search"),
- name="pages",
- icon_name="folder-open-inverse",
- order=100,
- )
- def is_shown(self, request):
- return user_has_any_page_permission(request.user)
- @hooks.register("register_admin_search_area")
- def register_pages_search_area():
- return PageSearchArea()
- @hooks.register("register_group_permission_panel")
- def register_collection_permissions_panel():
- return GroupCollectionManagementPermissionFormSet
- class CollectionsMenuItem(MenuItem):
- def is_shown(self, request):
- return collection_permission_policy.user_has_any_permission(
- request.user, ["add", "change", "delete"]
- )
- @hooks.register("register_settings_menu_item")
- def register_collections_menu_item():
- return CollectionsMenuItem(
- _("Collections"),
- reverse("wagtailadmin_collections:index"),
- icon_name="folder-open-1",
- order=700,
- )
- class WorkflowsMenuItem(MenuItem):
- def is_shown(self, request):
- if not getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
- return False
- return workflow_permission_policy.user_has_any_permission(
- request.user, ["add", "change", "delete"]
- )
- class WorkflowTasksMenuItem(MenuItem):
- def is_shown(self, request):
- if not getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True):
- return False
- return task_permission_policy.user_has_any_permission(
- request.user, ["add", "change", "delete"]
- )
- @hooks.register("register_settings_menu_item")
- def register_workflows_menu_item():
- return WorkflowsMenuItem(
- _("Workflows"),
- reverse("wagtailadmin_workflows:index"),
- icon_name="tasks",
- order=100,
- )
- @hooks.register("register_settings_menu_item")
- def register_workflow_tasks_menu_item():
- return WorkflowTasksMenuItem(
- _("Workflow tasks"),
- reverse("wagtailadmin_workflows:task_index"),
- icon_name="thumbtack",
- order=150,
- )
- @hooks.register("register_page_listing_buttons")
- def page_listing_buttons(page, page_perms, next_url=None):
- if page_perms.can_edit():
- yield PageListingButton(
- _("Edit"),
- reverse("wagtailadmin_pages:edit", args=[page.id]),
- attrs={
- "aria-label": _("Edit '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=10,
- )
- if page.has_unpublished_changes and page.is_previewable():
- yield PageListingButton(
- _("View draft"),
- reverse("wagtailadmin_pages:view_draft", args=[page.id]),
- attrs={
- "aria-label": _("Preview draft version of '%(title)s'")
- % {"title": page.get_admin_display_title()},
- "rel": "noreferrer",
- },
- priority=20,
- )
- if page.live and page.url:
- yield PageListingButton(
- _("View live"),
- page.url,
- attrs={
- "rel": "noreferrer",
- "aria-label": _("View live version of '%(title)s'")
- % {"title": page.get_admin_display_title()},
- },
- priority=30,
- )
- if page_perms.can_add_subpage():
- yield PageListingButton(
- _("Add child page"),
- reverse("wagtailadmin_pages:add_subpage", args=[page.id]),
- attrs={
- "aria-label": _("Add a child page to '%(title)s' ")
- % {"title": page.get_admin_display_title()}
- },
- priority=40,
- )
- yield ButtonWithDropdownFromHook(
- _("More"),
- hook_name="register_page_listing_more_buttons",
- page=page,
- page_perms=page_perms,
- next_url=next_url,
- attrs={
- "target": "_blank",
- "rel": "noreferrer",
- "title": _("View more options for '%(title)s'")
- % {"title": page.get_admin_display_title()},
- },
- priority=50,
- )
- @hooks.register("register_page_listing_more_buttons")
- def page_listing_more_buttons(page, page_perms, next_url=None):
- if page_perms.can_move():
- yield Button(
- _("Move"),
- reverse("wagtailadmin_pages:move", args=[page.id]),
- attrs={
- "title": _("Move page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=10,
- )
- if page_perms.can_copy():
- url = reverse("wagtailadmin_pages:copy", args=[page.id])
- if next_url:
- url += "?" + urlencode({"next": next_url})
- yield Button(
- _("Copy"),
- url,
- attrs={
- "title": _("Copy page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=20,
- )
- if page_perms.can_delete():
- url = reverse("wagtailadmin_pages:delete", args=[page.id])
- # After deleting the page, it is impossible to redirect to it.
- if next_url == reverse("wagtailadmin_explore", args=[page.id]):
- next_url = None
- if next_url:
- url += "?" + urlencode({"next": next_url})
- yield Button(
- _("Delete"),
- url,
- attrs={
- "title": _("Delete page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=30,
- )
- if page_perms.can_unpublish():
- url = reverse("wagtailadmin_pages:unpublish", args=[page.id])
- if next_url:
- url += "?" + urlencode({"next": next_url})
- yield Button(
- _("Unpublish"),
- url,
- attrs={
- "title": _("Unpublish page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=40,
- )
- if page_perms.can_view_revisions():
- yield Button(
- _("History"),
- reverse("wagtailadmin_pages:history", args=[page.id]),
- attrs={
- "title": _("View page history for '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=50,
- )
- if page_perms.can_reorder_children():
- yield Button(
- _("Sort menu order"),
- "?ordering=ord",
- attrs={
- "title": _("Change ordering of child pages of '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=60,
- )
- @hooks.register("register_page_header_buttons")
- def page_header_buttons(page, page_perms, next_url=None):
- if page_perms.can_edit():
- yield Button(
- _("Edit"),
- reverse("wagtailadmin_pages:edit", args=[page.id]),
- icon_name="edit",
- attrs={
- "title": _("Edit '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=10,
- )
- if page_perms.can_move():
- yield Button(
- _("Move"),
- reverse("wagtailadmin_pages:move", args=[page.id]),
- icon_name="arrow-right-full",
- attrs={
- "title": _("Move page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=20,
- )
- if page_perms.can_copy():
- url = reverse("wagtailadmin_pages:copy", args=[page.id])
- if next_url:
- url += "?" + urlencode({"next": next_url})
- yield Button(
- _("Copy"),
- url,
- icon_name="copy",
- attrs={
- "title": _("Copy page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=30,
- )
- if page_perms.can_add_subpage():
- yield Button(
- _("Add child page"),
- reverse("wagtailadmin_pages:add_subpage", args=[page.id]),
- icon_name="circle-plus",
- attrs={
- "aria-label": _("Add a child page to '%(title)s' ")
- % {"title": page.get_admin_display_title()},
- },
- priority=40,
- )
- if page_perms.can_delete():
- url = reverse("wagtailadmin_pages:delete", args=[page.id])
- # After deleting the page, it is impossible to redirect to it.
- if next_url == reverse("wagtailadmin_explore", args=[page.id]):
- next_url = None
- if next_url:
- url += "?" + urlencode({"next": next_url})
- yield Button(
- _("Delete"),
- url,
- icon_name="bin",
- attrs={
- "title": _("Delete page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=50,
- )
- if page_perms.can_unpublish():
- url = reverse("wagtailadmin_pages:unpublish", args=[page.id])
- if next_url:
- url += "?" + urlencode({"next": next_url})
- yield Button(
- _("Unpublish"),
- url,
- icon_name="download-alt",
- attrs={
- "title": _("Unpublish page '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=60,
- )
- if page_perms.can_reorder_children():
- url = reverse("wagtailadmin_explore", args=[page.id])
- url += "?ordering=ord"
- yield Button(
- _("Sort menu order"),
- url,
- icon_name="list-ul",
- attrs={
- "title": _("Change ordering of child pages of '%(title)s'")
- % {"title": page.get_admin_display_title()}
- },
- priority=70,
- )
- if Permission.objects.filter(
- content_type__app_label="simple_translation", codename="submit_translation"
- ):
- if (
- page_perms.user.has_perm("simple_translation.submit_translation")
- and not page.is_root()
- ):
- # If there's at least one locale that we haven't translated into yet, show "Translate this page" button
- has_locale_to_translate_to = Locale.objects.exclude(
- id__in=page.get_translations(inclusive=True).values_list(
- "locale_id", flat=True
- )
- ).exists()
- if has_locale_to_translate_to:
- url = reverse(
- "simple_translation:submit_page_translation", args=[page.id]
- )
- yield Button(
- _("Translate"),
- url,
- icon_name="globe",
- attrs={
- "title": _("Translate this page")
- % {"title": page.get_admin_display_title()}
- },
- priority=80,
- )
- @hooks.register("register_admin_urls")
- def register_viewsets_urls():
- viewsets.populate()
- return viewsets.get_urlpatterns()
- @hooks.register("register_rich_text_features")
- def register_core_features(features):
- features.register_converter_rule(
- "editorhtml",
- "link",
- [
- WhitelistRule("a", attribute_rule({"href": check_url})),
- LinkTypeRule("page", PageLinkHandler),
- ],
- )
- features.register_converter_rule(
- "editorhtml",
- "bold",
- [
- WhitelistRule("b", allow_without_attributes),
- WhitelistRule("strong", allow_without_attributes),
- ],
- )
- features.register_converter_rule(
- "editorhtml",
- "italic",
- [
- WhitelistRule("i", allow_without_attributes),
- WhitelistRule("em", allow_without_attributes),
- ],
- )
- headings_elements = ["h1", "h2", "h3", "h4", "h5", "h6"]
- for order, element in enumerate(headings_elements):
- features.register_converter_rule(
- "editorhtml", element, [WhitelistRule(element, allow_without_attributes)]
- )
- features.register_converter_rule(
- "editorhtml",
- "ol",
- [
- WhitelistRule("ol", allow_without_attributes),
- WhitelistRule("li", allow_without_attributes),
- ],
- )
- features.register_converter_rule(
- "editorhtml",
- "ul",
- [
- WhitelistRule("ul", allow_without_attributes),
- WhitelistRule("li", allow_without_attributes),
- ],
- )
- # Draftail
- features.register_editor_plugin(
- "draftail", "hr", draftail_features.BooleanFeature("enableHorizontalRule")
- )
- features.register_converter_rule(
- "contentstate",
- "hr",
- {
- "from_database_format": {
- "hr": HorizontalRuleHandler(),
- },
- "to_database_format": {
- "entity_decorators": {
- "HORIZONTAL_RULE": lambda props: DOM.create_element("hr")
- }
- },
- },
- )
- features.register_editor_plugin(
- "draftail",
- "h1",
- draftail_features.BlockFeature(
- {
- "icon": "h1",
- "type": "header-one",
- "description": gettext("Heading %(level)d") % {"level": 1},
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "h1",
- {
- "from_database_format": {
- "h1": BlockElementHandler("header-one"),
- },
- "to_database_format": {"block_map": {"header-one": "h1"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "h2",
- draftail_features.BlockFeature(
- {
- "icon": "h2",
- "type": "header-two",
- "description": gettext("Heading %(level)d") % {"level": 2},
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "h2",
- {
- "from_database_format": {
- "h2": BlockElementHandler("header-two"),
- },
- "to_database_format": {"block_map": {"header-two": "h2"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "h3",
- draftail_features.BlockFeature(
- {
- "icon": "h3",
- "type": "header-three",
- "description": gettext("Heading %(level)d") % {"level": 3},
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "h3",
- {
- "from_database_format": {
- "h3": BlockElementHandler("header-three"),
- },
- "to_database_format": {"block_map": {"header-three": "h3"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "h4",
- draftail_features.BlockFeature(
- {
- "icon": "h4",
- "type": "header-four",
- "description": gettext("Heading %(level)d") % {"level": 4},
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "h4",
- {
- "from_database_format": {
- "h4": BlockElementHandler("header-four"),
- },
- "to_database_format": {"block_map": {"header-four": "h4"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "h5",
- draftail_features.BlockFeature(
- {
- "icon": "h5",
- "type": "header-five",
- "description": gettext("Heading %(level)d") % {"level": 5},
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "h5",
- {
- "from_database_format": {
- "h5": BlockElementHandler("header-five"),
- },
- "to_database_format": {"block_map": {"header-five": "h5"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "h6",
- draftail_features.BlockFeature(
- {
- "icon": "h6",
- "type": "header-six",
- "description": gettext("Heading %(level)d") % {"level": 6},
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "h6",
- {
- "from_database_format": {
- "h6": BlockElementHandler("header-six"),
- },
- "to_database_format": {"block_map": {"header-six": "h6"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "ul",
- draftail_features.BlockFeature(
- {
- "type": "unordered-list-item",
- "icon": "list-ul",
- "description": gettext("Bulleted list"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "ul",
- {
- "from_database_format": {
- "ul": ListElementHandler("unordered-list-item"),
- "li": ListItemElementHandler(),
- },
- "to_database_format": {
- "block_map": {"unordered-list-item": {"element": "li", "wrapper": "ul"}}
- },
- },
- )
- features.register_editor_plugin(
- "draftail",
- "ol",
- draftail_features.BlockFeature(
- {
- "type": "ordered-list-item",
- "icon": "list-ol",
- "description": gettext("Numbered list"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "ol",
- {
- "from_database_format": {
- "ol": ListElementHandler("ordered-list-item"),
- "li": ListItemElementHandler(),
- },
- "to_database_format": {
- "block_map": {"ordered-list-item": {"element": "li", "wrapper": "ol"}}
- },
- },
- )
- features.register_editor_plugin(
- "draftail",
- "blockquote",
- draftail_features.BlockFeature(
- {
- "type": "blockquote",
- "icon": "openquote",
- "description": gettext("Blockquote"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "blockquote",
- {
- "from_database_format": {
- "blockquote": BlockElementHandler("blockquote"),
- },
- "to_database_format": {"block_map": {"blockquote": "blockquote"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "bold",
- draftail_features.InlineStyleFeature(
- {
- "type": "BOLD",
- "icon": "bold",
- "description": gettext("Bold"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "bold",
- {
- "from_database_format": {
- "b": InlineStyleElementHandler("BOLD"),
- "strong": InlineStyleElementHandler("BOLD"),
- },
- "to_database_format": {"style_map": {"BOLD": "b"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "italic",
- draftail_features.InlineStyleFeature(
- {
- "type": "ITALIC",
- "icon": "italic",
- "description": gettext("Italic"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "italic",
- {
- "from_database_format": {
- "i": InlineStyleElementHandler("ITALIC"),
- "em": InlineStyleElementHandler("ITALIC"),
- },
- "to_database_format": {"style_map": {"ITALIC": "i"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "link",
- draftail_features.EntityFeature(
- {
- "type": "LINK",
- "icon": "link",
- "description": gettext("Link"),
- # We want to enforce constraints on which links can be pasted into rich text.
- # Keep only the attributes Wagtail needs.
- "attributes": ["url", "id", "parentId"],
- "allowlist": {
- # Keep pasted links with http/https protocol, and not-pasted links (href = undefined).
- "href": "^(http:|https:|undefined$)",
- },
- },
- js=[
- "wagtailadmin/js/page-chooser-modal.js",
- ],
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "link",
- {
- "from_database_format": {
- "a[href]": ExternalLinkElementHandler("LINK"),
- 'a[linktype="page"]': PageLinkElementHandler("LINK"),
- },
- "to_database_format": {"entity_decorators": {"LINK": link_entity}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "superscript",
- draftail_features.InlineStyleFeature(
- {
- "type": "SUPERSCRIPT",
- "icon": "superscript",
- "description": gettext("Superscript"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "superscript",
- {
- "from_database_format": {
- "sup": InlineStyleElementHandler("SUPERSCRIPT"),
- },
- "to_database_format": {"style_map": {"SUPERSCRIPT": "sup"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "subscript",
- draftail_features.InlineStyleFeature(
- {
- "type": "SUBSCRIPT",
- "icon": "subscript",
- "description": gettext("Subscript"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "subscript",
- {
- "from_database_format": {
- "sub": InlineStyleElementHandler("SUBSCRIPT"),
- },
- "to_database_format": {"style_map": {"SUBSCRIPT": "sub"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "strikethrough",
- draftail_features.InlineStyleFeature(
- {
- "type": "STRIKETHROUGH",
- "icon": "strikethrough",
- "description": gettext("Strikethrough"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "strikethrough",
- {
- "from_database_format": {
- "s": InlineStyleElementHandler("STRIKETHROUGH"),
- },
- "to_database_format": {"style_map": {"STRIKETHROUGH": "s"}},
- },
- )
- features.register_editor_plugin(
- "draftail",
- "code",
- draftail_features.InlineStyleFeature(
- {
- "type": "CODE",
- "icon": "code",
- "description": gettext("Code"),
- }
- ),
- )
- features.register_converter_rule(
- "contentstate",
- "code",
- {
- "from_database_format": {
- "code": InlineStyleElementHandler("CODE"),
- },
- "to_database_format": {"style_map": {"CODE": "code"}},
- },
- )
- class LockedPagesMenuItem(MenuItem):
- def is_shown(self, request):
- return UserPagePermissionsProxy(request.user).can_remove_locks()
- class WorkflowReportMenuItem(MenuItem):
- def is_shown(self, request):
- return getattr(settings, "WAGTAIL_WORKFLOW_ENABLED", True)
- class SiteHistoryReportMenuItem(MenuItem):
- def is_shown(self, request):
- return UserPagePermissionsProxy(request.user).explorable_pages().exists()
- class AgingPagesReportMenuItem(MenuItem):
- def is_shown(self, request):
- return getattr(settings, "WAGTAIL_AGING_PAGES_ENABLED", True)
- @hooks.register("register_reports_menu_item")
- def register_locked_pages_menu_item():
- return LockedPagesMenuItem(
- _("Locked Pages"),
- reverse("wagtailadmin_reports:locked_pages"),
- icon_name="lock",
- order=700,
- )
- @hooks.register("register_reports_menu_item")
- def register_workflow_report_menu_item():
- return WorkflowReportMenuItem(
- _("Workflows"),
- reverse("wagtailadmin_reports:workflow"),
- icon_name="tasks",
- order=800,
- )
- @hooks.register("register_reports_menu_item")
- def register_workflow_tasks_report_menu_item():
- return WorkflowReportMenuItem(
- _("Workflow tasks"),
- reverse("wagtailadmin_reports:workflow_tasks"),
- icon_name="thumbtack",
- order=900,
- )
- @hooks.register("register_reports_menu_item")
- def register_site_history_report_menu_item():
- return SiteHistoryReportMenuItem(
- _("Site history"),
- reverse("wagtailadmin_reports:site_history"),
- icon_name="history",
- order=1000,
- )
- @hooks.register("register_reports_menu_item")
- def register_aging_pages_report_menu_item():
- return AgingPagesReportMenuItem(
- _("Aging pages"),
- reverse("wagtailadmin_reports:aging_pages"),
- icon_name="time",
- order=1100,
- )
- @hooks.register("register_admin_menu_item")
- def register_reports_menu():
- return SubmenuMenuItem(_("Reports"), reports_menu, icon_name="site", order=9000)
- @hooks.register("register_icons")
- def register_icons(icons):
- for icon in [
- "angle-double-left.svg",
- "angle-double-right.svg",
- "arrow-down-big.svg",
- "arrow-down.svg",
- "arrow-right-full.svg",
- "arrow-left.svg",
- "arrow-right.svg",
- "arrow-up-big.svg",
- "arrow-up.svg",
- "arrows-up-down.svg",
- "bars.svg",
- "bin.svg",
- "bold.svg",
- "breadcrumb-expand.svg",
- "caret-down.svg",
- "chain-broken.svg",
- "check.svg",
- "chevron-down.svg",
- "circle-check.svg",
- "circle-plus.svg",
- "clipboard-list.svg",
- "code.svg",
- "cog.svg",
- "cogs.svg",
- "copy.svg",
- "collapse-down.svg",
- "collapse-up.svg",
- "comment.svg",
- "comment-add.svg",
- "comment-add-reversed.svg",
- "cross.svg",
- "cut.svg",
- "date.svg",
- "desktop.svg",
- "doc-empty-inverse.svg",
- "doc-empty.svg",
- "doc-full-inverse.svg",
- "doc-full.svg", # aka file-text-alt
- "dots-vertical.svg",
- "dots-horizontal.svg",
- "download-alt.svg",
- "download.svg",
- "draft.svg",
- "duplicate.svg",
- "edit.svg",
- "ellipsis-v.svg",
- "expand-right.svg",
- "error.svg",
- "folder-inverse.svg",
- "folder-open-1.svg",
- "folder-open-inverse.svg",
- "folder.svg",
- "form.svg",
- "globe.svg",
- "grip.svg",
- "group.svg",
- "h1.svg",
- "h2.svg",
- "h3.svg",
- "h4.svg",
- "h5.svg",
- "h6.svg",
- "help.svg",
- "history.svg",
- "home.svg",
- "horizontalrule.svg",
- "image.svg", # aka picture
- "info-circle.svg",
- "italic.svg",
- "link.svg",
- "link-external.svg",
- "list-ol.svg",
- "list-ul.svg",
- "lock-open.svg",
- "lock.svg",
- "login.svg",
- "logout.svg",
- "mail.svg",
- "media.svg",
- "mobile-alt.svg",
- "no-view.svg",
- "openquote.svg",
- "order-down.svg",
- "order-up.svg",
- "order.svg",
- "password.svg",
- "pick.svg",
- "pilcrow.svg",
- "placeholder.svg", # aka marquee
- "plus-inverse.svg",
- "plus.svg",
- "radio-empty.svg",
- "radio-full.svg",
- "redirect.svg",
- "repeat.svg",
- "reset.svg",
- "resubmit.svg",
- "rotate.svg",
- "search.svg",
- "site.svg",
- "snippet.svg",
- "spinner.svg",
- "strikethrough.svg",
- "success.svg",
- "subscript.svg",
- "superscript.svg",
- "table.svg",
- "tablet-alt.svg",
- "tag.svg",
- "tasks.svg",
- "thumbtack.svg",
- "tick-inverse.svg",
- "tick.svg",
- "time.svg",
- "title.svg",
- "undo.svg",
- "uni52.svg", # Is this a redundant icon?
- "upload.svg",
- "user.svg",
- "view.svg",
- "wagtail-inverse.svg",
- "wagtail.svg",
- "warning.svg",
- ]:
- icons.append("wagtailadmin/icons/{}".format(icon))
- return icons
- @hooks.register("construct_homepage_summary_items")
- def add_pages_summary_item(request, items):
- items.insert(0, PagesSummaryItem(request))
- class PageAdminURLFinder:
- def __init__(self, user):
- self.page_perms = user and UserPagePermissionsProxy(user)
- def get_edit_url(self, instance):
- if self.page_perms and not self.page_perms.for_page(instance).can_edit():
- return None
- else:
- return reverse("wagtailadmin_pages:edit", args=(instance.pk,))
- register_admin_url_finder(Page, PageAdminURLFinder)
- class CollectionAdminURLFinder(ModelAdminURLFinder):
- permission_policy = collection_permission_policy
- edit_url_name = "wagtailadmin_collections:edit"
- register_admin_url_finder(Collection, CollectionAdminURLFinder)
- class WorkflowAdminURLFinder(ModelAdminURLFinder):
- permission_policy = workflow_permission_policy
- edit_url_name = "wagtailadmin_workflows:edit"
- register_admin_url_finder(Workflow, WorkflowAdminURLFinder)
- class WorkflowTaskAdminURLFinder(ModelAdminURLFinder):
- permission_policy = task_permission_policy
- edit_url_name = "wagtailadmin_workflows:edit_task"
- register_admin_url_finder(Task, WorkflowTaskAdminURLFinder)
- for action_class in [
- DeleteBulkAction,
- MoveBulkAction,
- PublishBulkAction,
- UnpublishBulkAction,
- ]:
- hooks.register("register_bulk_action", action_class)
|