def get_context_data(self, parent_context): context = super().get_context_data(parent_context) user_perms = UserPagePermissionsProxy(self.request.user) page = self.object if page.id: context.update({ "history_url": reverse("wagtailadmin_pages:history", args=(page.id, )), "lock_url": reverse("wagtailadmin_pages:lock", args=(page.id, )), "unlock_url": reverse("wagtailadmin_pages:unlock", args=(page.id, )), "user_can_lock": user_perms.for_page(page).can_lock(), "user_can_unlock": user_perms.for_page(page).can_unlock(), "locale": None, "translations": [], }) else: context.update({ "locale": None, "translations": [], }) if getattr(settings, "WAGTAIL_I18N_ENABLED", False): url_name = "wagtailadmin_pages:edit" if self.in_explorer: url_name = "wagtailadmin_explore" context.update({ "locale": page.locale, "translations": [{ "locale": translation.locale, "url": reverse(url_name, args=[translation.id]), } for translation in page.get_translations().only( "id", "locale", "depth").select_related("locale") if user_perms.for_page(translation).can_edit()], # The sum of translated pages plus 1 to account for the current page "translations_total": page.get_translations().count() + 1, }) context.update({ "model_name": self.model.get_verbose_name(), "model_description": self.model.get_page_description(), "status_templates": self.get_status_templates(context), }) return context
def __init__(self, request, **kwargs): self.request = request self.context = kwargs self.context["request"] = request page = self.context.get("page") user_page_permissions = UserPagePermissionsProxy(self.request.user) self.context["user_page_permissions"] = user_page_permissions if page: self.context[ "user_page_permissions_tester"] = user_page_permissions.for_page( page) self.menu_items = [] if page: task = page.current_workflow_task current_workflow_state = page.current_workflow_state is_final_task = (current_workflow_state and current_workflow_state.is_at_final_task) if task: actions = task.get_actions(page, request.user) workflow_menu_items = [] for name, label, launch_modal in actions: icon_name = "edit" if name == "approve": if is_final_task and not getattr( settings, "WAGTAIL_WORKFLOW_REQUIRE_REAPPROVAL_ON_EDIT", False, ): label = _("%(label)s and Publish") % { "label": label } icon_name = "success" item = WorkflowMenuItem(name, label, launch_modal, icon_name=icon_name) if item.is_shown(self.context): workflow_menu_items.append(item) self.menu_items.extend(workflow_menu_items) for menu_item in _get_base_page_action_menu_items(): if menu_item.is_shown(self.context): self.menu_items.append(menu_item) self.menu_items.sort(key=lambda item: item.order) for hook in hooks.get_hooks("construct_page_action_menu"): hook(self.menu_items, self.request, self.context) try: self.default_item = self.menu_items.pop(0) except IndexError: self.default_item = None
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context.update({ "page": self.page, "page_for_status": self.page_for_status, "content_type": self.page_content_type, "edit_handler": self.edit_handler, "errors_debug": self.errors_debug, "action_menu": PageActionMenu(self.request, view="edit", page=self.page), "preview_modes": self.page.preview_modes, "form": self.form, "next": self.next_url, "has_unsaved_changes": self.has_unsaved_changes, "page_locked": self.page_perms.page_locked(), "workflow_state": self.workflow_state if self.workflow_state and self.workflow_state.is_active else None, "current_task_state": self.page.current_workflow_task_state, "publishing_will_cancel_workflow": self.workflow_tasks and getattr(settings, "WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH", True), "locale": None, "translations": [], }) if getattr(settings, "WAGTAIL_I18N_ENABLED", False): user_perms = UserPagePermissionsProxy(self.request.user) context.update({ "locale": self.page.locale, "translations": [{ "locale": translation.locale, "url": reverse("wagtailadmin_pages:edit", args=[translation.id]), } for translation in self.page.get_translations().only( "id", "locale", "depth").select_related("locale") if user_perms.for_page(translation).can_edit()], }) return context
def execute(self, skip_permission_checks=False): super().execute(skip_permission_checks) if self.include_descendants: from wagtail.models import UserPagePermissionsProxy user_perms = UserPagePermissionsProxy(self.user) for live_descendant_page in (self.object.get_descendants().live( ).defer_streamfields().specific().iterator()): action = UnpublishPageAction(live_descendant_page) if user_perms.for_page(live_descendant_page).can_unpublish(): action.execute(skip_permission_checks=True)
def get_context_data(self, parent_context): context = super().get_context_data(parent_context) user_perms = UserPagePermissionsProxy(self.request.user) if self.page.id: context.update({ "lock_url": reverse("wagtailadmin_pages:lock", args=(self.page.id, )), "unlock_url": reverse("wagtailadmin_pages:unlock", args=(self.page.id, )), "user_can_lock": user_perms.for_page(self.page).can_lock(), "user_can_unlock": user_perms.for_page(self.page).can_unlock(), "locale": None, "translations": [], }) else: context.update({ "locale": None, "translations": [], }) if getattr(settings, "WAGTAIL_I18N_ENABLED", False): context.update({ "locale": self.page.locale, "translations": [{ "locale": translation.locale, "url": reverse("wagtailadmin_pages:edit", args=[translation.id]), } for translation in self.page.get_translations().only( "id", "locale", "depth").select_related("locale") if user_perms.for_page(translation).can_edit()], }) return context
def unpublish(request, page_id): page = get_object_or_404(Page, id=page_id).specific user_perms = UserPagePermissionsProxy(request.user) if not user_perms.for_page(page).can_unpublish(): raise PermissionDenied next_url = get_valid_next_url_from_request(request) if request.method == "POST": include_descendants = request.POST.get("include_descendants", False) for fn in hooks.get_hooks("before_unpublish_page"): result = fn(request, page) if hasattr(result, "status_code"): return result action = UnpublishPageAction(page, user=request.user, include_descendants=include_descendants) action.execute(skip_permission_checks=True) for fn in hooks.get_hooks("after_unpublish_page"): result = fn(request, page) if hasattr(result, "status_code"): return result messages.success( request, _("Page '{0}' unpublished.").format( page.get_admin_display_title()), buttons=[ messages.button( reverse("wagtailadmin_pages:edit", args=(page.id, )), _("Edit")) ], ) if next_url: return redirect(next_url) return redirect("wagtailadmin_explore", page.get_parent().id) return TemplateResponse( request, "wagtailadmin/pages/confirm_unpublish.html", { "page": page, "next": next_url, "live_descendant_count": page.get_descendants().live().count(), }, )
def revisions_unschedule(request, page_id, revision_id): page = get_object_or_404(Page, id=page_id).specific user_perms = UserPagePermissionsProxy(request.user) if not user_perms.for_page(page).can_unschedule(): raise PermissionDenied revision = get_object_or_404(page.revisions, id=revision_id) next_url = get_valid_next_url_from_request(request) subtitle = _('revision {0} of "{1}"').format( revision.id, page.get_admin_display_title()) if request.method == "POST": revision.approved_go_live_at = None revision.save(user=request.user, update_fields=["approved_go_live_at"]) messages.success( request, _('Version {0} of "{1}" unscheduled.').format( revision.id, page.get_admin_display_title()), buttons=[ messages.button( reverse("wagtailadmin_pages:edit", args=(page.id, )), _("Edit")) ], ) if next_url: return redirect(next_url) return redirect("wagtailadmin_pages:history", page.id) return TemplateResponse( request, "wagtailadmin/pages/revisions/confirm_unschedule.html", { "page": page, "revision": revision, "next": next_url, "subtitle": subtitle }, )
def execute(self, skip_permission_checks=False): self.check(skip_permission_checks=skip_permission_checks) self._unpublish_page( self.page, set_expired=self.set_expired, commit=self.commit, user=self.user, log_action=self.log_action, ) if self.include_descendants: from wagtail.models import UserPagePermissionsProxy user_perms = UserPagePermissionsProxy(self.user) for live_descendant_page in (self.page.get_descendants().live(). defer_streamfields().specific()): action = UnpublishPageAction(live_descendant_page) if user_perms.for_page(live_descendant_page).can_unpublish(): action.execute(skip_permission_checks=True)
def workflow_history(request, page_id): page = get_object_or_404(Page, id=page_id) user_perms = UserPagePermissionsProxy(request.user) if not user_perms.for_page(page).can_edit(): raise PermissionDenied workflow_states = WorkflowState.objects.filter( page=page).order_by("-created_at") paginator = Paginator(workflow_states, per_page=20) workflow_states = paginator.get_page(request.GET.get("p")) return TemplateResponse( request, "wagtailadmin/pages/workflow_history/index.html", { "page": page, "workflow_states": workflow_states, }, )
def workflow_history_detail(request, page_id, workflow_state_id): page = get_object_or_404(Page, id=page_id) user_perms = UserPagePermissionsProxy(request.user) if not user_perms.for_page(page).can_edit(): raise PermissionDenied workflow_state = get_object_or_404(WorkflowState, page=page, id=workflow_state_id) # Get QuerySet of all revisions that have existed during this workflow state # It's possible that the page is edited while the workflow is running, so some # tasks may be repeated. All tasks that have been completed no matter what # revision needs to be displayed on this page. page_revisions = PageRevision.objects.filter( page=page, id__in=TaskState.objects.filter( workflow_state=workflow_state).values_list("page_revision_id", flat=True), ).order_by("-created_at") # Now get QuerySet of tasks completed for each revision task_states_by_revision_task = [( page_revision, { task_state.task: task_state for task_state in TaskState.objects.filter( workflow_state=workflow_state, page_revision=page_revision) }, ) for page_revision in page_revisions] # Make sure task states are always in a consistent order # In some cases, they can be completed in a different order to what they are defined tasks = workflow_state.workflow.tasks.all() task_states_by_revision = [ (page_revision, [task_states_by_task.get(task, None) for task in tasks]) for page_revision, task_states_by_task in task_states_by_revision_task ] # Generate timeline completed_task_states = (TaskState.objects.filter( workflow_state=workflow_state).exclude( finished_at__isnull=True).exclude( status=TaskState.STATUS_CANCELLED)) timeline = [{ "time": workflow_state.created_at, "action": "workflow_started", "workflow_state": workflow_state, }] if workflow_state.status not in ( WorkflowState.STATUS_IN_PROGRESS, WorkflowState.STATUS_NEEDS_CHANGES, ): last_task = completed_task_states.order_by("finished_at").last() if last_task: timeline.append({ "time": last_task.finished_at + timedelta(milliseconds=1), "action": "workflow_completed", "workflow_state": workflow_state, }) for page_revision in page_revisions: timeline.append({ "time": page_revision.created_at, "action": "page_edited", "revision": page_revision, }) for task_state in completed_task_states: timeline.append({ "time": task_state.finished_at, "action": "task_completed", "task_state": task_state, }) timeline.sort(key=lambda t: t["time"]) timeline.reverse() return TemplateResponse( request, "wagtailadmin/pages/workflow_history/detail.html", { "page": page, "workflow_state": workflow_state, "tasks": tasks, "task_states_by_revision": task_states_by_revision, "timeline": timeline, }, )
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) bound_panel = self.edit_handler.get_bound_panel(request=self.request, instance=self.page, form=self.form) action_menu = PageActionMenu(self.request, view="create", parent_page=self.parent_page) context.update({ "content_type": self.page_content_type, "page_class": self.page_class, "parent_page": self.parent_page, "edit_handler": bound_panel, "action_menu": action_menu, "preview_modes": self.page.preview_modes, "form": self.form, "next": self.next_url, "has_unsaved_changes": self.has_unsaved_changes, "locale": None, "translations": [], "media": bound_panel.media + self.form.media + action_menu.media, }) if getattr(settings, "WAGTAIL_I18N_ENABLED", False): # Pages can be created in any language at the root level if self.parent_page.is_root(): translations = [{ "locale": locale, "url": reverse( "wagtailadmin_pages:add", args=[ self.page_content_type.app_label, self.page_content_type.model, self.parent_page.id, ], ) + "?" + urlencode({"locale": locale.language_code}), } for locale in Locale.objects.all()] else: user_perms = UserPagePermissionsProxy(self.request.user) translations = [ { "locale": translation.locale, "url": reverse( "wagtailadmin_pages:add", args=[ self.page_content_type.app_label, self.page_content_type.model, translation.id, ], ), } for translation in self.parent_page.get_translations( ).only("id", "locale").select_related("locale") if user_perms.for_page(translation).can_add_subpage() and self.page_class in translation.specific_class.creatable_subpage_models() and self.page_class.can_create_at(translation) ] context.update({ "locale": self.locale, "translations": translations, }) return context
def unpublish(request, page_id): page = get_object_or_404(Page, id=page_id).specific user_perms = UserPagePermissionsProxy(request.user) if not user_perms.for_page(page).can_unpublish(): raise PermissionDenied next_url = get_valid_next_url_from_request(request) pages_to_unpublish = {page} if getattr(settings, "WAGTAIL_I18N_ENABLED", False): for fn in hooks.get_hooks( "construct_translated_pages_to_cascade_actions"): fn_pages = fn([page], "unpublish") if fn_pages and isinstance(fn_pages, dict): for additional_pages in fn_pages.values(): pages_to_unpublish.update(additional_pages) pages_to_unpublish = list(pages_to_unpublish) if request.method == "POST": include_descendants = request.POST.get("include_descendants", False) for fn in hooks.get_hooks("before_unpublish_page"): result = fn(request, page) if hasattr(result, "status_code"): return result for page in pages_to_unpublish: action = UnpublishPageAction( page, user=request.user, include_descendants=include_descendants) action.execute(skip_permission_checks=True) for fn in hooks.get_hooks("after_unpublish_page"): result = fn(request, page) if hasattr(result, "status_code"): return result messages.success( request, _("Page '{0}' unpublished.").format( page.get_admin_display_title()), buttons=[ messages.button( reverse("wagtailadmin_pages:edit", args=(page.id, )), _("Edit")) ], ) if next_url: return redirect(next_url) return redirect("wagtailadmin_explore", page.get_parent().id) return TemplateResponse( request, "wagtailadmin/pages/confirm_unpublish.html", { "page": page, "next": next_url, "live_descendant_count": page.get_descendants().live().count(), "translation_count": len(pages_to_unpublish[1:]), "translation_descendant_count": sum([ p.get_descendants().filter( alias_of__isnull=True).live().count() for p in pages_to_unpublish[1:] ]), }, )
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) bound_panel = self.edit_handler.get_bound_panel(instance=self.page, request=self.request, form=self.form) action_menu = PageActionMenu( self.request, view="edit", page=self.page, lock=self.lock, locked_for_user=self.locked_for_user, ) side_panels = PageSidePanels( self.request, self.page_for_status, preview_enabled=True, comments_enabled=self.form.show_comments_toggle, ) context.update({ "page": self.page, "page_for_status": self.page_for_status, "content_type": self.page_content_type, "edit_handler": bound_panel, "errors_debug": self.errors_debug, "action_menu": action_menu, "side_panels": side_panels, "form": self.form, "next": self.next_url, "has_unsaved_changes": self.has_unsaved_changes, "page_locked": self.locked_for_user, "workflow_state": self.workflow_state if self.workflow_state and self.workflow_state.is_active else None, "current_task_state": self.page.current_workflow_task_state, "publishing_will_cancel_workflow": self.workflow_tasks and getattr(settings, "WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH", True), "locale": None, "translations": [], "media": bound_panel.media + self.form.media + action_menu.media + side_panels.media, }) if getattr(settings, "WAGTAIL_I18N_ENABLED", False): user_perms = UserPagePermissionsProxy(self.request.user) context.update({ "locale": self.page.locale, "translations": [{ "locale": translation.locale, "url": reverse("wagtailadmin_pages:edit", args=[translation.id]), } for translation in self.page.get_translations().only( "id", "locale", "depth").select_related("locale") if user_perms.for_page(translation).can_edit()], }) return context
def dispatch(self, request, *args, **kwargs): user_perms = UserPagePermissionsProxy(request.user) if not user_perms.for_page(self.object).can_unpublish(): raise PermissionDenied return super().dispatch(request, *args, **kwargs)