Example #1
0
def index(request):

    form = SearchForm(placeholder=_("Search something"))

    example_form = ExampleForm()

    messages.success(request, _("Success message"), buttons=[
        messages.button('', _('View live')),
        messages.button('', _('Edit'))
    ])
    messages.warning(request, _("Warning message"), buttons=[
        messages.button('', _('View live')),
        messages.button('', _('Edit'))
    ])
    messages.error(request, _("Error message"), buttons=[
        messages.button('', _('View live')),
        messages.button('', _('Edit'))
    ])

    paginator = Paginator(list(range(100)), 10)
    page = paginator.page(2)

    user = User(email='*****@*****.**')

    return render(request, 'wagtailstyleguide/base.html', {
        'search_form': form,
        'example_form': example_form,
        'example_page': page,
        'user': user,
    })
Example #2
0
def resend(request):
    to_email = request.session.get('to_email')
    host_link = request.session.get('host_link')
    username = request.session.get('username')

    if username is not None:
        user = User.objects.get(username=username)
        if user is not None:
            #  if user account is already activated
            if user.is_active:
                messages.error(request, 'Your account is already activated!')
                return redirect('members:account_home')
            #  if user account is not activated yet and user's inactive profile remains in db
            else:
                if send_validation_email(request, user, to_email, 'register'):
                    # reload session
                    request.session['host_link'] = host_link
                    return render(request, 'activate_account_popup.html',
                                  {'host_link': host_link})
        #  if user's inactive profile is removed from db
        else:
            print('in 404')
            messages.error(
                request,
                'Sorry, your registration has expired. Please sign up again')
        return redirect(reverse_lazy('members:signup'))
    else:
        messages.warning(request, "Invalid action")
        return render(request, 'activate_account_popup.html',
                      {'host_link': host_link})
Example #3
0
def index(request):

    form = SearchForm(placeholder=_("Search something"))

    example_form = ExampleForm()

    messages.success(request,
                     _("Success message"),
                     buttons=[
                         messages.button('', _('View live')),
                         messages.button('', _('Edit'))
                     ])
    messages.warning(request,
                     _("Warning message"),
                     buttons=[
                         messages.button('', _('View live')),
                         messages.button('', _('Edit'))
                     ])
    messages.error(request,
                   _("Error message"),
                   buttons=[
                       messages.button('', _('View live')),
                       messages.button('', _('Edit'))
                   ])

    paginator = Paginator(list(range(100)), 10)
    page = paginator.page(2)

    return TemplateResponse(request, 'wagtailstyleguide/base.html', {
        'search_form': form,
        'example_form': example_form,
        'example_page': page,
    })
Example #4
0
def newsletter_form_page_check_sendy_api(request, page):

    if isinstance(page, NewsletterFormPage):
        if not page.sendy_list_id:
            message = _(
                'There is no sendy_list_id set for page "%s". '
                "Therefore newsletter subscription will not work." % page
            )
            messages.warning(request, message)
        elif not settings.DEBUG:

            sendy_response = None
            try:
                sendy_response = sendy_api.subscriber_count(page.sendy_list_id)

                # Sendy will return an integer if the given list_id exists

                int(sendy_response)
            except (
                ConnectionError,
                NewConnectionError,
                MaxRetryError,
                ValueError,
            ) as e:
                message = (
                    _(
                        "There was a problem talking to Sendy API: %s. "
                        "Please check the sendy_list_id and try again."
                    )
                    % sendy_response
                    if sendy_response
                    else e
                )
                messages.warning(request, message)
Example #5
0
    def dispatch(self, request, *args, **kwargs):
        self.object = self.get_object()
        profile = self.object.userprofile

        self.is_approval = profile.assignment_status in (
            UserProfile.STATUS_CREATED,
            UserProfile.STATUS_AWAITING_APPROVAL,
        )
        if (
            settings.FEATURE_FLAGS['ENFORCE_STAFF_SSO_ON'] and
            self.is_approval and request.method == 'GET'
        ):
            # Warn the current user that this is an 'approval'
            message_text = (
                "This user is awaiting approval and will be automatically "
                "notified via email if added to a group that grants access "
                "to the Wagtail CMS."
            )
            if profile.self_assigned_group:
                # Preselect the user-selcted group in the form
                self.initial['groups'] = [profile.self_assigned_group.id]
                # Also mention this to the current user
                message_text += (
                    " They requested to be added to the '{}' group, so this "
                    "has been preselected for you under the 'Roles' tab."
                ).format(profile.self_assigned_group.name)

            messages.warning(request, message_text)
        return super().dispatch(request, *args, **kwargs)
Example #6
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_page_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=revision_page,
                                        request=request)
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.bind_to(form=form)

    user_avatar = render_to_string("wagtailadmin/shared/user_avatar.html",
                                   {"user": revision.user})

    messages.warning(
        request,
        mark_safe(
            _("You are viewing a previous version of this page from <b>%(created_at)s</b> by %(user)s"
              ) % {
                  "created_at": revision.created_at.strftime("%d %b %Y %H:%M"),
                  "user": user_avatar,
              }),
    )

    return TemplateResponse(
        request,
        "wagtailadmin/pages/edit.html",
        {
            "page":
            page,
            "revision":
            revision,
            "is_revision":
            True,
            "content_type":
            content_type,
            "edit_handler":
            edit_handler,
            "errors_debug":
            None,
            "action_menu":
            PageActionMenu(request, view="revisions_revert", page=page),
            "preview_modes":
            page.preview_modes,
            "form":
            form,  # Used in unit tests
        },
    )
Example #7
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_page_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=revision_page,
                                        request=request)
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.bind_to(form=form)

    user_avatar = render_to_string('wagtailadmin/shared/user_avatar.html',
                                   {'user': revision.user})

    messages.warning(
        request,
        mark_safe(
            _("You are viewing a previous version of this page from <b>%(created_at)s</b> by %(user)s"
              ) % {
                  'created_at': revision.created_at.strftime("%d %b %Y %H:%M"),
                  'user': user_avatar,
              }))

    return TemplateResponse(
        request,
        'wagtailadmin/pages/edit.html',
        {
            'page':
            page,
            'revision':
            revision,
            'is_revision':
            True,
            'content_type':
            content_type,
            'edit_handler':
            edit_handler,
            'errors_debug':
            None,
            'action_menu':
            PageActionMenu(request, view='revisions_revert', page=page),
            'preview_modes':
            page.preview_modes,
            'form':
            form,  # Used in unit tests
        })
def run_scan(request):
    site = Site.find_for_request(request)
    celery_status = get_celery_worker_status()
    if 'ERROR' not in celery_status:
        broken_link_scan(site)
    else:
        messages.warning(
            request,
            _('No celery workers are running, the scan was not conducted.'))

    return redirect('wagtaillinkchecker')
Example #9
0
    def add_legacy_moderation_warning(self):
        # Check for revisions still undergoing moderation and warn - this is for the old moderation system
        if self.latest_revision and self.latest_revision.submitted_for_moderation:
            buttons = []

            if self.page.live:
                buttons.append(self.get_compare_with_live_message_button())

            messages.warning(self.request,
                             _("This page is currently awaiting moderation"),
                             buttons=buttons)
Example #10
0
 def get(self, *args, **kwargs):
     new_mails = self.instance.get_new_mail()
     if new_mails:
         messages.success(
             self.request,
             f"Mail updated for {self.instance}: {len(new_mails)} new mails"
         )
     else:
         messages.warning(
             self.request,
             f"Mail updated for {self.instance}: no new mails")
     return redirect(self.index_url)
Example #11
0
File: edit.py Project: tnir/wagtail
    def get(self, request):
        if self.lock:
            lock_message = self.lock.get_message(self.request.user)
            if lock_message:
                if isinstance(self.lock,
                              BasicLock) and self.page_perms.can_unlock():
                    lock_message = format_html(
                        '{} <span class="buttons"><button type="button" class="button button-small button-secondary" data-action-lock-unlock data-url="{}">{}</button></span>',
                        lock_message,
                        reverse("wagtailadmin_pages:unlock",
                                args=(self.page.id, )),
                        _("Unlock"),
                    )

                if (isinstance(self.lock, ScheduledForPublishLock)
                        and self.page_perms.can_unschedule()):
                    scheduled_revision = self.page.revisions.defer().get(
                        approved_go_live_at__isnull=False)
                    lock_message = format_html(
                        '{} <span class="buttons"><button type="button" class="button button-small button-secondary" data-action-lock-unlock data-url="{}">{}</button></span>',
                        lock_message,
                        reverse(
                            "wagtailadmin_pages:revisions_unschedule",
                            args=[self.page.id, scheduled_revision.pk],
                        ),
                        _("Cancel scheduled publish"),
                    )

                if self.locked_for_user:
                    messages.error(self.request,
                                   lock_message,
                                   extra_tags="lock")
                else:
                    messages.warning(self.request,
                                     lock_message,
                                     extra_tags="lock")

        self.form = self.form_class(
            instance=self.page,
            subscription=self.subscription,
            parent_page=self.parent,
            for_user=self.request.user,
        )
        self.has_unsaved_changes = False
        self.add_legacy_moderation_warning()
        self.page_for_status = self.get_page_for_status()

        return self.render_to_response(self.get_context_data())
Example #12
0
    def post(self, request, *args, **kwargs):
        if '_refund-error' in request.POST:
            # Refund error, add error message and redirect to change view.
            msg = _("There was an error while trying to refund order.")
            messages.error(request, msg)

        if '_refund-success' in request.POST:
            # Refund success, add success message and redirect to change view.
            failed = int(request.POST['_refund-success'])
            if failed:
                msg = _("The Order “{}” was only partially refunded.")
                messages.warning(request, msg.format(self.instance))
            else:
                msg = _("The Order “{}” was successfully refunded.")
                messages.success(request, msg.format(self.instance))

        return redirect(self.edit_url)
Example #13
0
 def get_redirect_url(self, *args, **kwargs):
     index = models.ScrutinIndex.objects.last()
     if not index:
         root = models.SitePage.objects.first()
         if not root:
             messages.error(
                 self.request,
                 "Impossible de trouver la racine de votre site.",
             )
             return reverse('wagtailadmin_home')
         messages.warning(
             self.request,
             "Impossible de trouver une page d'index des formulaires. "
             "Veillez d'abord en ajouter une.",
         )
         return reverse('wagtailadmin_pages:add_subpage', args=(root.id, ))
     return reverse('wagtailadmin_pages:add_subpage', args=(index.id, ))
def import_page(request):
    """
    View for the import page.
    """
    if request.method == 'POST':
        form = forms.ImportPage(request.POST, request.FILES)

        if form.is_valid():

            # Read fields on the submitted form.
            form_file = form.cleaned_data['file']
            form_parentpage = form.cleaned_data['parent_page']

            # Import pages and get the response.
            num_uploaded, num_failed, response = importing.import_page(form_file, form_parentpage)

            # Show messages depending on the response.
            if not num_failed:
                # All pages are imported.
                messages.success(
                    request, ungettext("Imported %(count)s page.", "Imported %(count)s pages.", num_uploaded) 
                    % {'count': num_uploaded}
                )
            elif not num_uploaded:
                # None of the pages are imported.
                messages.error(
                    request, ungettext("Failed to import %(count)s page. %(reason)s", "Failed to import %(count)s pages. %(reason)s", num_failed) 
                    % {'count': num_failed, 'reason': response}
                )
            else:
                # Some pages are imported and some failed.
                messages.warning(
                    request, ungettext("Failed to import %(failed)s out of %(total)s page. %(reason)s", "Failed to import %(failed)s out of %(total)s pages. %(reason)s", num_failed + num_uploaded) 
                    % {'failed': num_failed, 'total': num_failed + num_uploaded, 'reason': response}
                )

            # Redirect client to the parent page view on admin.
            return redirect('wagtailadmin_explore', form_parentpage.pk)
    else:
        form = forms.ImportPage()
        
        # Redirect client to form.
        return render(request, 'wagtailimportexport/import-page.html', {
            'form': form,
        })
Example #15
0
def custom_wagtail_page_delete(request, page_id):
    """
    Currently, ProtectedError exception is not caught in Wagtail admin.
    This workaround shows warning to the user if the page model like Fund, Round
    can not be deleted instead of raising 500.
    More details at https://github.com/wagtail/wagtail/issues/1602
    Once the issue is fixed in Wagtail core, we can remove this workaround.
    """
    try:
        return delete(request, page_id)
    except ProtectedError as e:
        protected_details = ", ".join([str(obj) for obj in e.protected_objects])
        page = get_object_or_404(Page, id=page_id).specific
        parent_id = page.get_parent().id
        messages.warning(request, _("Page '{0}' can't be deleted because is in use in '{1}'.").format(
            page.get_admin_display_title(), protected_details
        ))
        return redirect('wagtailadmin_explore', parent_id)
Example #16
0
def disable_delete(request, page):
    """Disable deleting of speakers/events

    We don't want it because it breaks urls and connections between speakers and events.
    We disable it only during POST request (so in the final stage of deleting). This means
    delete confirmation page is displayed. From there user can alternatively unpublish the page.
    """
    if (
        request.user.username != "admin"
        and page.specific_class in [Speaker, Event]
        and request.method == "POST"
    ):
        messages.warning(
            request,
            _("Page '{0}' can not be deleted. You can only unpublish it.").format(
                page.get_admin_display_title()
            ),
        )
        return redirect("wagtailadmin_pages:delete", page.pk)
Example #17
0
def index(request):

    form = SearchForm(placeholder=_("Search something"))

    example_form = ExampleForm()

    messages.success(
        request,
        _("Success message"),
        buttons=[
            messages.button("", _("View live")),
            messages.button("", _("Edit"))
        ],
    )
    messages.warning(
        request,
        _("Warning message"),
        buttons=[
            messages.button("", _("View live")),
            messages.button("", _("Edit"))
        ],
    )
    messages.error(
        request,
        _("Error message"),
        buttons=[
            messages.button("", _("View live")),
            messages.button("", _("Edit"))
        ],
    )

    paginator = Paginator(list(range(100)), 10)
    page = paginator.page(2)

    return TemplateResponse(
        request,
        "wagtailstyleguide/base.html",
        {
            "search_form": form,
            "example_form": example_form,
            "example_page": page,
        },
    )
Example #18
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_page_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=revision_page,
                                        request=request)
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.bind_to(form=form)

    user_avatar = render_to_string('wagtailadmin/shared/user_avatar.html', {'user': revision.user})

    messages.warning(request, mark_safe(
        _("You are viewing a previous revision of this page from <b>%(created_at)s</b> by %(user)s") % {
            'created_at': revision.created_at.strftime("%d %b %Y %H:%M"),
            'user': user_avatar,
        }
    ))

    return render(request, 'wagtailadmin/pages/edit.html', {
        'page': page,
        'revision': revision,
        'is_revision': True,
        'content_type': content_type,
        'edit_handler': edit_handler,
        'errors_debug': None,
        'action_menu': PageActionMenu(request, view='revisions_revert', page=page),
        'preview_modes': page.preview_modes,
        'form': form,  # Used in unit tests
    })
def my_hook_function(request, page):

    conf = apps.get_app_config('wagtail_cloudfront_invalidate')

    if not conf.enabled:
        return

    try:

        invalidate(conf.AWS_ACCESS_KEY_ID,
                   conf.AWS_SECRET_ACCESS_KEY,
                   conf.CLOUDFRONT_DISTRIBUTION_ID,
                   items=[
                       page.get_url(),
                   ])

    except ParamValidationError:
        messages.warning(
            request,
            _('Cloudfront Invalidation Error. Check that your AWS access key, secret key and Cloudfront distribution ID are set.'
              ))
    except Exception as e:
        messages.warning(request, e.__str__())
Example #20
0
 def dry_run(self):
     """Crible les lignes en vue de l'affichage de la confirmation."""
     ok, warn, ko = self.crible_data()
     if ok and not warn and not ko:
         messages.success(
             self.request,
             "L'import est valide et peut être poursuivi.",
         )
     elif warn and not ko:
         messages.warning(
             self.request,
             "L'import est valide mais demande une attention "
             "particulière avant d'être poursuivi.",
         )
     elif ko:
         messages.error(
             self.request,
             "L'import ne peut être poursuivi du fait d'erreurs.",
             buttons=[
                 messages.button(reverse('import:index'),
                                 "Re-tenter un import"),
             ],
         )
     return ok, warn, ko
Example #21
0
def edit(request, page_id):
    real_page_record = get_object_or_404(Page, id=page_id)
    latest_revision = real_page_record.get_latest_revision()
    content_type = real_page_record.cached_content_type
    page_class = real_page_record.specific_class

    if page_class is None:
        raise PageClassNotFoundError(
            f"The page '{real_page_record}' cannot be edited because the "
            f"model class used to create it ({content_type.app_label}."
            f"{content_type.model}) can no longer be found in the codebase. "
            "This usually happens as a result of switching between git "
            "branches without running migrations to trigger the removal of "
            "unused ContentTypes. To edit the page, you will need to switch "
            "back to a branch where the model class is still present."
        )

    page = real_page_record.get_latest_revision_as_page()
    parent = page.get_parent()

    page_perms = page.permissions_for_user(request.user)

    if not page_perms.can_edit():
        raise PermissionDenied

    next_url = get_valid_next_url_from_request(request)

    for fn in hooks.get_hooks('before_edit_page'):
        result = fn(request, page)
        if hasattr(result, 'status_code'):
            return result

    edit_handler = page_class.get_edit_handler()
    edit_handler = edit_handler.bind_to(instance=page, request=request)
    form_class = edit_handler.get_form_class()

    if request.method == 'GET':
        if page_perms.user_has_lock():
            if page.locked_at:
                lock_message = format_html(_("<b>Page '{}' was locked</b> by <b>you</b> on <b>{}</b>."), page.get_admin_display_title(), page.locked_at.strftime("%d %b %Y %H:%M"))
            else:
                lock_message = format_html(_("<b>Page '{}' is locked</b> by <b>you</b>."), page.get_admin_display_title())

            lock_message += format_html(
                '<span class="buttons"><button class="button button-small button-secondary" data-locking-action="{}">{}</button></span>',
                reverse('wagtailadmin_pages:unlock', args=(page.id,)),
                _("Unlock")
            )
            messages.warning(request, lock_message, extra_tags='lock')

        elif page.locked and page_perms.page_locked():
            # the page can also be locked at a permissions level if in a workflow, on a task the user is not a reviewer for
            # this should be indicated separately
            if page.locked_by and page.locked_at:
                lock_message = format_html(_("<b>Page '{}' was locked</b> by <b>{}</b> on <b>{}</b>."), page.get_admin_display_title(), str(page.locked_by), page.locked_at.strftime("%d %b %Y %H:%M"))
            else:
                # Page was probably locked with an old version of Wagtail, or a script
                lock_message = format_html(_("<b>Page '{}' is locked</b>."), page.get_admin_display_title())

            if page_perms.can_unlock():
                lock_message += format_html(
                    '<span class="buttons"><button class="button button-small button-secondary" data-locking-action="{}">{}</button></span>',
                    reverse('wagtailadmin_pages:unlock', args=(page.id,)),
                    _("Unlock")
                )
            messages.error(request, lock_message, extra_tags='lock')

        if page.current_workflow_state:
            workflow_state = page.current_workflow_state
            workflow = workflow_state.workflow
            workflow_tasks = workflow_state.all_tasks_with_status()
            task = workflow_state.current_task_state.task
            if (
                workflow_state.status != WorkflowState.STATUS_NEEDS_CHANGES
                and task.specific.page_locked_for_user(page, request.user)
            ):
                # Check for revisions still undergoing moderation and warn
                if len(workflow_tasks) == 1:
                    # If only one task in workflow, show simple message
                    workflow_info = _("This page is currently awaiting moderation.")
                else:
                    workflow_info = format_html(
                        _("This page is awaiting <b>'{}'</b> in the <b>'{}'</b> workflow."),
                        task.name, workflow.name
                    )
                messages.error(request, mark_safe(workflow_info + " " + _("Only reviewers for this task can edit the page.")),
                               extra_tags="lock")
    # Check for revisions still undergoing moderation and warn - this is for the old moderation system
    if latest_revision and latest_revision.submitted_for_moderation:
        buttons = []

        if page.live:
            buttons.append(messages.button(
                reverse('wagtailadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)),
                _('Compare with live version')
            ))

        messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons)

    # Show current workflow state if set, default to last workflow state
    workflow_state = page.current_workflow_state or page.workflow_states.order_by('created_at').last()
    if workflow_state:
        workflow_tasks = workflow_state.all_tasks_with_status()
    else:
        workflow_tasks = []

    errors_debug = None

    if request.method == 'POST':
        form = form_class(request.POST, request.FILES, instance=page,
                          parent_page=parent)

        is_publishing = False
        is_submitting = False
        is_restarting_workflow = False
        is_reverting = False
        is_saving = False
        is_cancelling_workflow = bool(request.POST.get('action-cancel-workflow')) and workflow_state and workflow_state.user_can_cancel(request.user)
        if is_cancelling_workflow:
            workflow_state.cancel(user=request.user)
            # do this here so even if the page is locked due to not having permissions, the original submitter can still cancel the workflow

        if form.is_valid() and not page_perms.page_locked():
            page = form.save(commit=False)

            is_publishing = bool(request.POST.get('action-publish')) and page_perms.can_publish()
            is_submitting = bool(request.POST.get('action-submit')) and page_perms.can_submit_for_moderation()
            is_restarting_workflow = bool(request.POST.get('action-restart-workflow')) and page_perms.can_submit_for_moderation() and workflow_state and workflow_state.user_can_cancel(request.user)
            is_reverting = bool(request.POST.get('revision'))

            is_performing_workflow_action = bool(request.POST.get('action-workflow-action'))
            if is_performing_workflow_action:
                workflow_action = request.POST['workflow-action-name']
                available_actions = page.current_workflow_task.get_actions(page, request.user)
                available_action_names = [name for name, verbose_name, modal in available_actions]
                if workflow_action not in available_action_names:
                    # prevent this action
                    is_performing_workflow_action = False

            is_saving = True
            has_content_changes = form.has_changed()

            if is_restarting_workflow:
                workflow_state.cancel(user=request.user)

            # If a revision ID was passed in the form, get that revision so its
            # date can be referenced in notification messages
            if is_reverting:
                previous_revision = get_object_or_404(page.revisions, id=request.POST.get('revision'))

            if is_performing_workflow_action and not has_content_changes:
                # don't save a new revision, as we're just going to update the page's
                # workflow state with no content changes
                revision = latest_revision
            else:
                # Save revision
                revision = page.save_revision(
                    user=request.user,
                    log_action=True,  # Always log the new revision on edit
                    previous_revision=(previous_revision if is_reverting else None)
                )

            # store submitted go_live_at for messaging below
            go_live_at = page.go_live_at

            # Publish
            if is_publishing:
                for fn in hooks.get_hooks('before_publish_page'):
                    result = fn(request, page)
                    if hasattr(result, 'status_code'):
                        return result

                revision.publish(
                    user=request.user,
                    changed=has_content_changes,
                    previous_revision=(previous_revision if is_reverting else None)
                )

                # Need to reload the page because the URL may have changed, and we
                # need the up-to-date URL for the "View Live" button.
                page = page.specific_class.objects.get(pk=page.pk)

                for fn in hooks.get_hooks('after_publish_page'):
                    result = fn(request, page)
                    if hasattr(result, 'status_code'):
                        return result

            # Submit
            if is_submitting or is_restarting_workflow:
                if workflow_state and workflow_state.status == WorkflowState.STATUS_NEEDS_CHANGES:
                    # If the workflow was in the needs changes state, resume the existing workflow on submission
                    workflow_state.resume(request.user)
                else:
                    # Otherwise start a new workflow
                    workflow = page.get_workflow()
                    workflow.start(page, request.user)

            if is_performing_workflow_action:
                extra_workflow_data_json = request.POST.get('workflow-action-extra-data', '{}')
                extra_workflow_data = json.loads(extra_workflow_data_json)
                page.current_workflow_task.on_action(page.current_workflow_task_state, request.user, workflow_action, **extra_workflow_data)

        # Notifications
        if is_publishing:
            if go_live_at and go_live_at > timezone.now():
                # Page has been scheduled for publishing in the future

                if is_reverting:
                    message = _(
                        "Version from {0} of page '{1}' has been scheduled for publishing."
                    ).format(
                        previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                        page.get_admin_display_title()
                    )
                else:
                    if page.live:
                        message = _(
                            "Page '{0}' is live and this version has been scheduled for publishing."
                        ).format(
                            page.get_admin_display_title()
                        )

                    else:
                        message = _(
                            "Page '{0}' has been scheduled for publishing."
                        ).format(
                            page.get_admin_display_title()
                        )

                messages.success(request, message, buttons=[
                    messages.button(
                        reverse('wagtailadmin_pages:edit', args=(page.id,)),
                        _('Edit')
                    )
                ])

            else:
                # Page is being published now

                if is_reverting:
                    message = _(
                        "Version from {0} of page '{1}' has been published."
                    ).format(
                        previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                        page.get_admin_display_title()
                    )
                else:
                    message = _(
                        "Page '{0}' has been published."
                    ).format(
                        page.get_admin_display_title()
                    )

                buttons = []
                if page.url is not None:
                    buttons.append(messages.button(page.url, _('View live'), new_window=True))
                buttons.append(messages.button(reverse('wagtailadmin_pages:edit', args=(page_id,)), _('Edit')))
                messages.success(request, message, buttons=buttons)

        elif is_submitting:

            message = _(
                "Page '{0}' has been submitted for moderation."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message, buttons=[
                messages.button(
                    reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                    _('View draft'),
                    new_window=True
                ),
                messages.button(
                    reverse('wagtailadmin_pages:edit', args=(page_id,)),
                    _('Edit')
                )
            ])

        elif is_cancelling_workflow:
            message = _(
                "Workflow on page '{0}' has been cancelled."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message, buttons=[
                messages.button(
                    reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                    _('View draft'),
                    new_window=True
                ),
                messages.button(
                    reverse('wagtailadmin_pages:edit', args=(page_id,)),
                    ('Edit')
                )
            ])

        elif is_restarting_workflow:

            message = _(
                "Workflow on page '{0}' has been restarted."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message, buttons=[
                messages.button(
                    reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                    _('View draft'),
                    new_window=True
                ),
                messages.button(
                    reverse('wagtailadmin_pages:edit', args=(page_id,)),
                    _('Edit')
                )
            ])

        elif is_reverting:
            message = _(
                "Page '{0}' has been replaced with version from {1}."
            ).format(
                page.get_admin_display_title(),
                previous_revision.created_at.strftime("%d %b %Y %H:%M")
            )

            messages.success(request, message)
        elif is_saving:
            message = _(
                "Page '{0}' has been updated."
            ).format(
                page.get_admin_display_title()
            )

            messages.success(request, message)

        if is_saving:
            for fn in hooks.get_hooks('after_edit_page'):
                result = fn(request, page)
                if hasattr(result, 'status_code'):
                    return result

            if is_publishing or is_submitting or is_restarting_workflow or is_performing_workflow_action:
                # we're done here - redirect back to the explorer
                if next_url:
                    # redirect back to 'next' url if present
                    return redirect(next_url)
                # redirect back to the explorer
                return redirect('wagtailadmin_explore', page.get_parent().id)
            else:
                # Just saving - remain on edit page for further edits
                target_url = reverse('wagtailadmin_pages:edit', args=[page.id])
                if next_url:
                    # Ensure the 'next' url is passed through again if present
                    target_url += '?next=%s' % urlquote(next_url)
                return redirect(target_url)
        else:
            if page_perms.page_locked():
                messages.error(request, _("The page could not be saved as it is locked"))
            else:
                messages.validation_error(
                    request, _("The page could not be saved due to validation errors"), form
                )
            errors_debug = (
                repr(form.errors)
                + repr([
                    (name, formset.errors)
                    for (name, formset) in form.formsets.items()
                    if formset.errors
                ])
            )
            has_unsaved_changes = True
    else:
        form = form_class(instance=page, parent_page=parent)
        has_unsaved_changes = False

    edit_handler = edit_handler.bind_to(form=form)

    # Check for revisions still undergoing moderation and warn
    if latest_revision and latest_revision.submitted_for_moderation:
        buttons = []

        if page.live:
            buttons.append(messages.button(
                reverse('wagtailadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)),
                _('Compare with live version')
            ))

        messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons)

    if page.live and page.has_unpublished_changes:
        # Page status needs to present the version of the page containing the correct live URL
        page_for_status = real_page_record.specific
    else:
        page_for_status = page

    return TemplateResponse(request, 'wagtailadmin/pages/edit.html', {
        'page': page,
        'page_for_status': page_for_status,
        'content_type': content_type,
        'edit_handler': edit_handler,
        'errors_debug': errors_debug,
        'action_menu': PageActionMenu(request, view='edit', page=page),
        'preview_modes': page.preview_modes,
        'form': form,
        'next': next_url,
        'has_unsaved_changes': has_unsaved_changes,
        'page_locked': page_perms.page_locked(),
        'workflow_state': workflow_state if workflow_state and workflow_state.is_active else None,
        'current_task_state': page.current_workflow_task_state,
        'publishing_will_cancel_workflow': workflow_tasks and getattr(settings, 'WAGTAIL_WORKFLOW_CANCEL_ON_PUBLISH', True)
    })
Example #22
0
    def get(self, request):
        if self.page_perms.user_has_lock():
            if self.page.locked_at:
                lock_message = format_html(
                    _("<b>Page '{}' was locked</b> by <b>you</b> on <b>{}</b>."
                      ), self.page.get_admin_display_title(),
                    self.page.locked_at.strftime("%d %b %Y %H:%M"))
            else:
                lock_message = format_html(
                    _("<b>Page '{}' is locked</b> by <b>you</b>."),
                    self.page.get_admin_display_title())

            lock_message += format_html(
                '<span class="buttons"><button class="button button-small button-secondary" data-locking-action="{}">{}</button></span>',
                reverse('wagtailadmin_pages:unlock', args=(self.page.id, )),
                _("Unlock"))
            messages.warning(self.request, lock_message, extra_tags='lock')

        elif self.page.locked and self.page_perms.page_locked():
            # the page can also be locked at a permissions level if in a workflow, on a task the user is not a reviewer for
            # this should be indicated separately
            if self.page.locked_by and self.page.locked_at:
                lock_message = format_html(
                    _("<b>Page '{}' was locked</b> by <b>{}</b> on <b>{}</b>."
                      ), self.page.get_admin_display_title(),
                    str(self.page.locked_by),
                    self.page.locked_at.strftime("%d %b %Y %H:%M"))
            else:
                # Page was probably locked with an old version of Wagtail, or a script
                lock_message = format_html(_("<b>Page '{}' is locked</b>."),
                                           self.page.get_admin_display_title())

            if self.page_perms.can_unlock():
                lock_message += format_html(
                    '<span class="buttons"><button class="button button-small button-secondary" data-locking-action="{}">{}</button></span>',
                    reverse('wagtailadmin_pages:unlock',
                            args=(self.page.id, )), _("Unlock"))
            messages.error(self.request, lock_message, extra_tags='lock')

        if self.page.current_workflow_state:
            workflow = self.workflow_state.workflow
            task = self.workflow_state.current_task_state.task
            if (self.workflow_state.status !=
                    WorkflowState.STATUS_NEEDS_CHANGES
                    and task.specific.page_locked_for_user(
                        self.page, self.request.user)):
                # Check for revisions still undergoing moderation and warn
                if len(self.workflow_tasks) == 1:
                    # If only one task in workflow, show simple message
                    workflow_info = _(
                        "This page is currently awaiting moderation.")
                else:
                    workflow_info = format_html(
                        _("This page is awaiting <b>'{}'</b> in the <b>'{}'</b> workflow."
                          ), task.name, workflow.name)
                messages.error(
                    self.request,
                    mark_safe(
                        workflow_info + " " +
                        _("Only reviewers for this task can edit the page.")),
                    extra_tags="lock")

        self.form = self.form_class(instance=self.page,
                                    parent_page=self.parent)
        self.has_unsaved_changes = False
        self.edit_handler = self.edit_handler.bind_to(form=self.form)
        self.add_legacy_moderation_warning()
        self.page_for_status = self.get_page_for_status()

        return self.render_to_response(self.get_context_data())
def edit(request, page_id):
    real_page_record = get_object_or_404(Page, id=page_id)
    latest_revision = real_page_record.get_latest_revision()
    page = real_page_record.get_latest_revision_as_page()
    parent = page.get_parent()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    for fn in hooks.get_hooks('before_edit_page'):
        result = fn(request, page)
        if hasattr(result, 'status_code'):
            return result

    edit_handler = page_class.get_edit_handler()
    form_class = edit_handler.get_form_class()

    next_url = get_valid_next_url_from_request(request)

    errors_debug = None

    if request.method == 'POST':
        form = form_class(request.POST, request.FILES, instance=page,
                          parent_page=parent)

        if form.is_valid() and not page.locked:
            page = form.save(commit=False)

            is_publishing = bool(request.POST.get('action-publish')) and page_perms.can_publish()
            is_submitting = bool(request.POST.get('action-submit'))
            is_reverting = bool(request.POST.get('revision'))

            # If a revision ID was passed in the form, get that revision so its
            # date can be referenced in notification messages
            if is_reverting:
                previous_revision = get_object_or_404(page.revisions, id=request.POST.get('revision'))

            # Save revision
            revision = page.save_revision(
                user=request.user,
                submitted_for_moderation=is_submitting,
            )
            # store submitted go_live_at for messaging below
            go_live_at = page.go_live_at

            # Publish
            if is_publishing:
                revision.publish()
                # Need to reload the page because the URL may have changed, and we
                # need the up-to-date URL for the "View Live" button.
                page = page.specific_class.objects.get(pk=page.pk)

            # Notifications
            if is_publishing:
                if go_live_at and go_live_at > timezone.now():
                    # Page has been scheduled for publishing in the future

                    if is_reverting:
                        message = _(
                            "Revision from {0} of page '{1}' has been scheduled for publishing."
                        ).format(
                            previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                            page.get_admin_display_title()
                        )
                    else:
                        if page.live:
                            message = _(
                                "Page '{0}' is live and this revision has been scheduled for publishing."
                            ).format(
                                page.get_admin_display_title()
                            )
                        else:
                            message = _(
                                "Page '{0}' has been scheduled for publishing."
                            ).format(
                                page.get_admin_display_title()
                            )

                    messages.success(request, message, buttons=[
                        messages.button(
                            reverse('wagtailadmin_pages:edit', args=(page.id,)),
                            _('Edit')
                        )
                    ])

                else:
                    # Page is being published now

                    if is_reverting:
                        message = _(
                            "Revision from {0} of page '{1}' has been published."
                        ).format(
                            previous_revision.created_at.strftime("%d %b %Y %H:%M"),
                            page.get_admin_display_title()
                        )
                    else:
                        message = _(
                            "Page '{0}' has been published."
                        ).format(
                            page.get_admin_display_title()
                        )

                    buttons = []
                    if page.url is not None:
                        buttons.append(messages.button(page.url, _('View live'), new_window=True))
                    buttons.append(messages.button(reverse('wagtailadmin_pages:edit', args=(page_id,)), _('Edit')))
                    messages.success(request, message, buttons=buttons)

            elif is_submitting:

                message = _(
                    "Page '{0}' has been submitted for moderation."
                ).format(
                    page.get_admin_display_title()
                )

                messages.success(request, message, buttons=[
                    messages.button(
                        reverse('wagtailadmin_pages:view_draft', args=(page_id,)),
                        _('View draft'),
                        new_window=True
                    ),
                    messages.button(
                        reverse('wagtailadmin_pages:edit', args=(page_id,)),
                        _('Edit')
                    )
                ])

                if not send_notification(page.get_latest_revision().id, 'submitted', request.user.pk):
                    messages.error(request, _("Failed to send notifications to moderators"))

            else:  # Saving

                if is_reverting:
                    message = _(
                        "Page '{0}' has been replaced with revision from {1}."
                    ).format(
                        page.get_admin_display_title(),
                        previous_revision.created_at.strftime("%d %b %Y %H:%M")
                    )
                else:
                    message = _(
                        "Page '{0}' has been updated."
                    ).format(
                        page.get_admin_display_title()
                    )

                messages.success(request, message)

            for fn in hooks.get_hooks('after_edit_page'):
                result = fn(request, page)
                if hasattr(result, 'status_code'):
                    return result

            if is_publishing or is_submitting:
                # we're done here - redirect back to the explorer
                if next_url:
                    # redirect back to 'next' url if present
                    return redirect(next_url)
                # redirect back to the explorer
                return redirect('wagtailadmin_explore', page.get_parent().id)
            else:
                # Just saving - remain on edit page for further edits
                target_url = reverse('wagtailadmin_pages:edit', args=[page.id])
                if next_url:
                    # Ensure the 'next' url is passed through again if present
                    target_url += '?next=%s' % urlquote(next_url)
                return redirect(target_url)
        else:
            if page.locked:
                messages.error(request, _("The page could not be saved as it is locked"))
            else:
                messages.validation_error(
                    request, _("The page could not be saved due to validation errors"), form
                )

            edit_handler = edit_handler.bind_to_instance(instance=page,
                                                         form=form,
                                                         request=request)
            errors_debug = (
                repr(edit_handler.form.errors) +
                repr([
                    (name, formset.errors)
                    for (name, formset) in edit_handler.form.formsets.items()
                    if formset.errors
                ])
            )
            has_unsaved_changes = True
    else:
        form = form_class(instance=page, parent_page=parent)
        edit_handler = edit_handler.bind_to_instance(instance=page, form=form, request=request)
        has_unsaved_changes = False

    # Check for revisions still undergoing moderation and warn
    if latest_revision and latest_revision.submitted_for_moderation:
        buttons = []

        if page.live:
            buttons.append(messages.button(
                reverse('wagtailadmin_pages:revisions_compare', args=(page.id, 'live', latest_revision.id)),
                _('Compare with live version')
            ))

        messages.warning(request, _("This page is currently awaiting moderation"), buttons=buttons)

    if page.live and page.has_unpublished_changes:
        # Page status needs to present the version of the page containing the correct live URL
        page_for_status = real_page_record.specific
    else:
        page_for_status = page

    return render(request, 'wagtailadmin/pages/edit.html', {
        'page': page,
        'page_for_status': page_for_status,
        'content_type': content_type,
        'edit_handler': edit_handler,
        'errors_debug': errors_debug,
        'preview_modes': page.preview_modes,
        'form': form,
        'next': next_url,
        'has_unsaved_changes': has_unsaved_changes,
    })
def edit_translation(request, translation, instance):
    if isinstance(instance, Page):
        # Page
        # Note: Edit permission is already checked by the edit page view

        page_perms = instance.permissions_for_user(request.user)

        is_live = instance.live
        is_locked = instance.locked

        if instance.live_revision:
            last_published_at = instance.live_revision.created_at
            last_published_by = instance.live_revision.user
        else:
            last_published_at = instance.last_published_at
            last_published_by = None

        if instance.live:
            live_url = instance.full_url
        else:
            live_url = None

        can_publish = page_perms.can_publish()
        can_unpublish = page_perms.can_unpublish()
        can_lock = page_perms.can_lock()
        can_unlock = page_perms.can_unlock()
        can_delete = page_perms.can_delete()

    else:
        # Snippet
        # Note: Edit permission is already checked by the edit snippet view

        is_live = True
        is_locked = False
        last_published_at = None
        last_published_by = None
        live_url = None

        can_publish = True
        can_unpublish = False
        can_lock = False
        can_unlock = False
        can_delete = request.user.has_perm(
            get_permission_name("delete", instance.__class__)
        )

    source_instance = translation.source.get_source_instance()

    if request.method == "POST":
        if request.POST.get("action") == "publish":
            if isinstance(instance, Page):
                if not page_perms.can_publish():
                    raise PermissionDenied

            try:
                translation.save_target(user=request.user, publish=True)

            except ValidationError:
                messages.error(
                    request,
                    _(
                        "New validation errors were found when publishing '{object}' in {locale}. Please fix them or click publish again to ignore these translations for now."
                    ).format(
                        object=str(instance),
                        locale=translation.target_locale.get_display_name(),
                    ),
                )

            else:
                # Refresh instance to title in success message is up to date
                instance.refresh_from_db()

                string_segments = translation.source.stringsegment_set.all().order_by(
                    "order"
                )
                string_translations = string_segments.get_translations(
                    translation.target_locale
                )

                # Using annotate_translation as this ignores errors by default (so both errors and missing segments treated the same)
                if (
                    string_segments.annotate_translation(translation.target_locale)
                    .filter(translation__isnull=True)
                    .exists()
                ):
                    # One or more strings had an error
                    messages.warning(
                        request,
                        _(
                            "Published '{object}' in {locale} with missing translations - see below."
                        ).format(
                            object=str(instance),
                            locale=translation.target_locale.get_display_name(),
                        ),
                    )

                else:
                    messages.success(
                        request,
                        _("Published '{object}' in {locale}.").format(
                            object=str(instance),
                            locale=translation.target_locale.get_display_name(),
                        ),
                    )

        return redirect(request.path)

    string_segments = translation.source.stringsegment_set.all().order_by("order")
    string_translations = string_segments.get_translations(translation.target_locale)

    overridable_segments = translation.source.overridablesegment_set.all().order_by(
        "order"
    )
    segment_overrides = overridable_segments.get_overrides(translation.target_locale)
    related_object_segments = (
        translation.source.relatedobjectsegment_set.all().order_by("order")
    )

    tab_helper = TabHelper(source_instance)

    breadcrumb = []
    title_segment_id = None
    if isinstance(instance, Page):
        # find the closest common ancestor of the pages that this user has direct explore permission
        # (i.e. add/edit/publish/lock) over; this will be the root of the breadcrumb
        cca = get_explorable_root_page(request.user)
        if cca:
            breadcrumb = [
                {
                    "id": page.id,
                    "isRoot": page.is_root(),
                    "title": page.title,
                    "exploreUrl": reverse("wagtailadmin_explore_root")
                    if page.is_root()
                    else reverse("wagtailadmin_explore", args=[page.id]),
                }
                for page in instance.get_ancestors(inclusive=False).descendant_of(
                    cca, inclusive=True
                )
            ]

        # Set to the ID of a string segment that represents the title.
        # If this segment has a translation, the title will be replaced with that translation.
        try:
            title_segment_id = string_segments.get(context__path="title").id
        except StringSegment.DoesNotExist:
            pass

    machine_translator = None
    translator = get_machine_translator()
    if translator and translator.can_translate(
        translation.source.locale, translation.target_locale
    ):
        machine_translator = {
            "name": translator.display_name,
            "url": reverse("wagtail_localize:machine_translate", args=[translation.id]),
        }

    segments = []

    for segment in string_segments:
        try:
            location_info = get_segment_location_info(
                source_instance,
                tab_helper,
                segment.context.path,
                segment.context.get_field_path(source_instance),
            )
        except FieldHasNoEditPanelError:
            continue

        segments.append(
            {
                "type": "string",
                "id": segment.id,
                "contentPath": segment.context.path,
                "source": segment.string.data,
                "location": location_info,
                "editUrl": reverse(
                    "wagtail_localize:edit_string_translation",
                    kwargs={
                        "translation_id": translation.id,
                        "string_segment_id": segment.id,
                    },
                ),
                "order": segment.order,
            }
        )

    for segment in overridable_segments:
        try:
            location_info = get_segment_location_info(
                source_instance,
                tab_helper,
                segment.context.path,
                segment.context.get_field_path(source_instance),
                widget=True,
            )
        except FieldHasNoEditPanelError:
            continue

        segments.append(
            {
                "type": "synchronised_value",
                "id": segment.id,
                "contentPath": segment.context.path,
                "location": location_info,
                "value": segment.data,
                "editUrl": reverse(
                    "wagtail_localize:edit_override",
                    kwargs={
                        "translation_id": translation.id,
                        "overridable_segment_id": segment.id,
                    },
                ),
                "order": segment.order,
            }
        )

    def get_source_object_info(segment):
        instance = segment.get_source_instance()

        if isinstance(instance, Page):
            return {
                "title": str(instance),
                "isLive": instance.live,
                "liveUrl": instance.full_url,
                "editUrl": reverse("wagtailadmin_pages:edit", args=[instance.id]),
                "createTranslationRequestUrl": reverse(
                    "wagtail_localize:submit_page_translation", args=[instance.id]
                ),
            }

        else:
            return {
                "title": str(instance),
                "isLive": True,
                "editUrl": reverse(
                    "wagtailsnippets:edit",
                    args=[
                        instance._meta.app_label,
                        instance._meta.model_name,
                        quote(instance.id),
                    ],
                ),
                "createTranslationRequestUrl": reverse(
                    "wagtail_localize:submit_snippet_translation",
                    args=[
                        instance._meta.app_label,
                        instance._meta.model_name,
                        quote(instance.id),
                    ],
                ),
            }

    def get_dest_object_info(segment):
        instance = segment.object.get_instance_or_none(translation.target_locale)
        if not instance:
            return

        if isinstance(instance, Page):
            return {
                "title": str(instance),
                "isLive": instance.live,
                "liveUrl": instance.full_url,
                "editUrl": reverse("wagtailadmin_pages:edit", args=[instance.id]),
            }

        else:
            return {
                "title": str(instance),
                "isLive": True,
                "editUrl": reverse(
                    "wagtailsnippets:edit",
                    args=[
                        instance._meta.app_label,
                        instance._meta.model_name,
                        quote(instance.id),
                    ],
                ),
            }

    def get_translation_progress(segment, locale):
        try:
            translation = Translation.objects.get(
                source__object_id=segment.object_id, target_locale=locale, enabled=True
            )

        except Translation.DoesNotExist:
            return None

        total_segments, translated_segments = translation.get_progress()

        return {
            "totalSegments": total_segments,
            "translatedSegments": translated_segments,
        }

    for segment in related_object_segments:
        try:
            location_info = get_segment_location_info(
                source_instance,
                tab_helper,
                segment.context.path,
                segment.context.get_field_path(source_instance),
            )
        except FieldHasNoEditPanelError:
            continue

        segments.append(
            {
                "type": "related_object",
                "id": segment.id,
                "contentPath": segment.context.path,
                "location": location_info,
                "order": segment.order,
                "source": get_source_object_info(segment),
                "dest": get_dest_object_info(segment),
                "translationProgress": get_translation_progress(
                    segment, translation.target_locale
                ),
            }
        )

    # Order segments by how they appear in the content panels
    # segment['location']['order'] is the content panel ordering
    # segment['order'] is the model field ordering
    # User's expect segments to follow the panel ordering as that's the ordering
    # that is used in the page editor of the source page. However, segments that
    # come from the same streamfield/inline panel are given the same value for
    # panel ordering, so we need to order by model field ordering as well (all
    # segments have a unique value for model field ordering)
    segments.sort(key=lambda segment: (segment["location"]["order"], segment["order"]))

    # Display a warning to the user if the schema of the source model has been updated since the source was last updated
    if translation.source.schema_out_of_date():
        messages.warning(
            request,
            _(
                "The data model for '{model_name}' has been changed since the last translation sync. "
                "If any new fields have been added recently, these may not be visible until the next translation sync."
            ).format(model_name=capfirst(source_instance._meta.verbose_name)),
        )

    return render(
        request,
        "wagtail_localize/admin/edit_translation.html",
        {
            "translation": translation,
            # These props are passed directly to the TranslationEditor react component
            "props": json.dumps(
                {
                    "adminBaseUrl": reverse("wagtailadmin_home"),
                    "object": {
                        "title": str(instance),
                        "titleSegmentId": title_segment_id,
                        "isLive": is_live,
                        "isLocked": is_locked,
                        "lastPublishedDate": last_published_at.strftime(DATE_FORMAT)
                        if last_published_at is not None
                        else None,
                        "lastPublishedBy": UserSerializer(last_published_by).data
                        if last_published_by is not None
                        else None,
                        "liveUrl": live_url,
                    },
                    "breadcrumb": breadcrumb,
                    "tabs": tab_helper.tabs_with_slugs,
                    "sourceLocale": {
                        "code": translation.source.locale.language_code,
                        "displayName": translation.source.locale.get_display_name(),
                    },
                    "locale": {
                        "code": translation.target_locale.language_code,
                        "displayName": translation.target_locale.get_display_name(),
                    },
                    "translations": [
                        {
                            "title": str(translated_instance),
                            "locale": {
                                "code": translated_instance.locale.language_code,
                                "displayName": translated_instance.locale.get_display_name(),
                            },
                            "editUrl": reverse(
                                "wagtailadmin_pages:edit", args=[translated_instance.id]
                            )
                            if isinstance(translated_instance, Page)
                            else reverse(
                                "wagtailsnippets:edit",
                                args=[
                                    translated_instance._meta.app_label,
                                    translated_instance._meta.model_name,
                                    quote(translated_instance.id),
                                ],
                            ),
                        }
                        for translated_instance in instance.get_translations().select_related(
                            "locale"
                        )
                    ],
                    "perms": {
                        "canPublish": can_publish,
                        "canUnpublish": can_unpublish,
                        "canLock": can_lock,
                        "canUnlock": can_unlock,
                        "canDelete": can_delete,
                    },
                    "links": {
                        "downloadPofile": reverse(
                            "wagtail_localize:download_pofile", args=[translation.id]
                        ),
                        "uploadPofile": reverse(
                            "wagtail_localize:upload_pofile", args=[translation.id]
                        ),
                        "unpublishUrl": reverse(
                            "wagtailadmin_pages:unpublish", args=[instance.id]
                        )
                        if isinstance(instance, Page)
                        else None,
                        "lockUrl": reverse(
                            "wagtailadmin_pages:lock", args=[instance.id]
                        )
                        if isinstance(instance, Page)
                        else None,
                        "unlockUrl": reverse(
                            "wagtailadmin_pages:unlock", args=[instance.id]
                        )
                        if isinstance(instance, Page)
                        else None,
                        "deleteUrl": reverse(
                            "wagtailadmin_pages:delete", args=[instance.id]
                        )
                        if isinstance(instance, Page)
                        else reverse(
                            "wagtailsnippets:delete",
                            args=[
                                instance._meta.app_label,
                                instance._meta.model_name,
                                quote(instance.pk),
                            ],
                        ),
                        "stopTranslationUrl": reverse(
                            "wagtail_localize:stop_translation", args=[translation.id]
                        ),
                    },
                    "previewModes": [
                        {
                            "mode": mode,
                            "label": label,
                            "url": reverse(
                                "wagtail_localize:preview_translation",
                                args=[translation.id],
                            )
                            if mode == instance.default_preview_mode
                            else reverse(
                                "wagtail_localize:preview_translation",
                                args=[translation.id, mode],
                            ),
                        }
                        for mode, label in (
                            instance.preview_modes if isinstance(instance, Page) else []
                        )
                    ],
                    "machineTranslator": machine_translator,
                    "segments": segments,
                    # We serialize the translation data using Django REST Framework.
                    # This gives us a consistent representation with the APIs so we
                    # can dynamically update translations in the view.
                    "initialStringTranslations": StringTranslationSerializer(
                        string_translations,
                        many=True,
                        context={"translation_source": translation.source},
                    ).data,
                    "initialOverrides": SegmentOverrideSerializer(
                        segment_overrides,
                        many=True,
                        context={"translation_source": translation.source},
                    ).data,
                },
                cls=DjangoJSONEncoder,
            ),
        },
    )
Example #25
0
 def get(self, request, *args, **kwargs):
     if self.instance.is_fully_booked:
         messages.warning(request, _('This course is fully booked.'))
     return super().get(request, *args, **kwargs)
Example #26
0
 def _add_warning_message(self):
     messages.warning(self.request, self.get_warning_message())
Example #27
0
def machine_translate(request, translation_id):
    translation = get_object_or_404(Translation, id=translation_id)

    instance = translation.get_target_instance()
    if not user_can_edit_instance(request.user, instance):
        raise PermissionDenied

    translator = get_machine_translator()
    if translator is None:
        raise Http404

    if not translator.can_translate(translation.source.locale,
                                    translation.target_locale):
        raise Http404

    # Get segments
    segments = defaultdict(list)
    for string_segment in translation.source.stringsegment_set.all(
    ).select_related("context", "string"):
        segment = StringSegmentValue(
            string_segment.context.path,
            string_segment.string.as_value()).with_order(string_segment.order)
        if string_segment.attrs:
            segment.attrs = json.loads(string_segment.attrs)

        # Don't translate if there already is a translation
        if StringTranslation.objects.filter(
                translation_of_id=string_segment.string_id,
                locale=translation.target_locale,
                context_id=string_segment.context_id,
        ).exists():
            continue

        segments[segment.string].append(
            (string_segment.string_id, string_segment.context_id))

    if segments:
        translations = translator.translate(translation.source.locale,
                                            translation.target_locale,
                                            segments.keys())

        with transaction.atomic():
            for string, contexts in segments.items():
                for string_id, context_id in contexts:
                    StringTranslation.objects.get_or_create(
                        translation_of_id=string_id,
                        locale=translation.target_locale,
                        context_id=context_id,
                        defaults={
                            'data': translations[string].data,
                            'translation_type':
                            StringTranslation.TRANSLATION_TYPE_MACHINE,
                            'tool_name': translator.display_name,
                            'last_translated_by': request.user,
                            'has_error': False,
                            'field_error': "",
                        })

        messages.success(
            request,
            _("Successfully translated with {}.").format(
                translator.display_name))

    else:
        messages.warning(request, _("There isn't anything left to translate."))

    # Work out where to redirect to
    next_url = get_valid_next_url_from_request(request)
    if not next_url:
        # Note: You should always provide a next URL when using this view!
        next_url = reverse('wagtailadmin_home')

    return redirect(next_url)
Example #28
0
def edit_translation(request, translation, instance):
    if isinstance(instance, Page):
        # Page
        # Note: Edit permission is already checked by the edit page view

        page_perms = instance.permissions_for_user(request.user)

        is_live = instance.live
        is_locked = instance.locked

        if instance.live_revision:
            last_published_at = instance.live_revision.created_at
            last_published_by = instance.live_revision.user
        else:
            last_published_at = instance.last_published_at
            last_published_by = None

        if instance.live:
            live_url = instance.full_url
        else:
            live_url = None

        can_publish = page_perms.can_publish()
        can_unpublish = page_perms.can_unpublish()
        can_lock = page_perms.can_lock()
        can_unlock = page_perms.can_unlock()
        can_delete = page_perms.can_delete()

    else:
        # Snippet
        # Note: Edit permission is already checked by the edit snippet view

        is_live = True
        is_locked = False
        last_published_at = None
        last_published_by = None
        live_url = None

        can_publish = True
        can_unpublish = False
        can_lock = False
        can_unlock = False
        can_delete = request.user.has_perm(
            get_permission_name('delete', instance.__class__))

    source_instance = translation.source.get_source_instance()

    if request.method == 'POST':
        if request.POST.get('action') == 'publish':
            if isinstance(instance, Page):
                if not page_perms.can_publish():
                    raise PermissionDenied

            try:
                translation.save_target(user=request.user, publish=True)

            except ValidationError:
                messages.error(
                    request,
                    _("New validation errors were found when publishing '{object}' in {locale}. Please fix them or click publish again to ignore these translations for now."
                      ).format(
                          object=str(instance),
                          locale=translation.target_locale.get_display_name()))

            else:
                # Refresh instance to title in success message is up to date
                instance.refresh_from_db()

                string_segments = translation.source.stringsegment_set.all(
                ).order_by('order')
                string_translations = string_segments.get_translations(
                    translation.target_locale)

                # Using annotate_translation as this ignores errors by default (so both errors and missing segments treated the same)
                if string_segments.annotate_translation(
                        translation.target_locale).filter(
                            translation__isnull=True).exists():
                    # One or more strings had an error
                    messages.warning(
                        request,
                        _("Published '{object}' in {locale} with missing translations - see below."
                          ).format(object=str(instance),
                                   locale=translation.target_locale.
                                   get_display_name()))

                else:
                    messages.success(
                        request,
                        _("Published '{object}' in {locale}.").format(
                            object=str(instance),
                            locale=translation.target_locale.get_display_name(
                            )))

        return redirect(request.path)

    string_segments = translation.source.stringsegment_set.all().order_by(
        'order')
    string_translations = string_segments.get_translations(
        translation.target_locale)

    overridable_segments = translation.source.overridablesegment_set.all(
    ).order_by('order')
    segment_overrides = overridable_segments.get_overrides(
        translation.target_locale)
    related_object_segments = translation.source.relatedobjectsegment_set.all(
    ).order_by('order')

    tab_helper = TabHelper(source_instance)

    breadcrumb = []
    title_segment_id = None
    if isinstance(instance, Page):
        # find the closest common ancestor of the pages that this user has direct explore permission
        # (i.e. add/edit/publish/lock) over; this will be the root of the breadcrumb
        cca = get_explorable_root_page(request.user)
        if cca:
            breadcrumb = [{
                'id':
                page.id,
                'isRoot':
                page.is_root(),
                'title':
                page.title,
                'exploreUrl':
                reverse('wagtailadmin_explore_root') if page.is_root() else
                reverse('wagtailadmin_explore', args=[page.id]),
            } for page in instance.get_ancestors(
                inclusive=False).descendant_of(cca, inclusive=True)]

        # Set to the ID of a string segment that represents the title.
        # If this segment has a translation, the title will be replaced with that translation.
        try:
            title_segment_id = string_segments.get(context__path='title').id
        except StringSegment.DoesNotExist:
            pass

    machine_translator = None
    translator = get_machine_translator()
    if translator and translator.can_translate(translation.source.locale,
                                               translation.target_locale):
        machine_translator = {
            'name':
            translator.display_name,
            'url':
            reverse('wagtail_localize:machine_translate',
                    args=[translation.id]),
        }

    string_segment_data = [{
        'type':
        'string',
        'id':
        segment.id,
        'contentPath':
        segment.context.path,
        'source':
        segment.string.data,
        'location':
        get_segment_location_info(source_instance, tab_helper,
                                  segment.context.path),
        'editUrl':
        reverse('wagtail_localize:edit_string_translation',
                kwargs={
                    'translation_id': translation.id,
                    'string_segment_id': segment.id
                }),
        'order':
        segment.order,
    } for segment in string_segments]
    syncronised_value_segment_data = [{
        'type':
        'synchronised_value',
        'id':
        segment.id,
        'contentPath':
        segment.context.path,
        'location':
        get_segment_location_info(source_instance,
                                  tab_helper,
                                  segment.context.path,
                                  widget=True),
        'value':
        segment.data,
        'editUrl':
        reverse('wagtail_localize:edit_override',
                kwargs={
                    'translation_id': translation.id,
                    'overridable_segment_id': segment.id
                }),
        'order':
        segment.order,
    } for segment in overridable_segments]

    def get_source_object_info(segment):
        instance = segment.get_source_instance()

        if isinstance(instance, Page):
            return {
                'title':
                str(instance),
                'isLive':
                instance.live,
                'liveUrl':
                instance.full_url,
                'editUrl':
                reverse('wagtailadmin_pages:edit', args=[instance.id]),
                'createTranslationRequestUrl':
                reverse('wagtail_localize:submit_page_translation',
                        args=[instance.id]),
            }

        else:
            return {
                'title':
                str(instance),
                'isLive':
                True,
                'editUrl':
                reverse('wagtailsnippets:edit',
                        args=[
                            instance._meta.app_label,
                            instance._meta.model_name,
                            quote(instance.id)
                        ]),
                'createTranslationRequestUrl':
                reverse('wagtail_localize:submit_snippet_translation',
                        args=[
                            instance._meta.app_label,
                            instance._meta.model_name,
                            quote(instance.id)
                        ]),
            }

    def get_dest_object_info(segment):
        instance = segment.object.get_instance_or_none(
            translation.target_locale)
        if not instance:
            return

        if isinstance(instance, Page):
            return {
                'title': str(instance),
                'isLive': instance.live,
                'liveUrl': instance.full_url,
                'editUrl': reverse('wagtailadmin_pages:edit',
                                   args=[instance.id]),
            }

        else:
            return {
                'title':
                str(instance),
                'isLive':
                True,
                'editUrl':
                reverse('wagtailsnippets:edit',
                        args=[
                            instance._meta.app_label,
                            instance._meta.model_name,
                            quote(instance.id)
                        ]),
            }

    def get_translation_progress(segment, locale):
        try:
            translation = Translation.objects.get(
                source__object_id=segment.object_id,
                target_locale=locale,
                enabled=True)

        except Translation.DoesNotExist:
            return None

        total_segments, translated_segments = translation.get_progress()

        return {
            'totalSegments': total_segments,
            'translatedSegments': translated_segments,
        }

    related_object_segment_data = [{
        'type':
        'related_object',
        'id':
        segment.id,
        'contentPath':
        segment.context.path,
        'location':
        get_segment_location_info(source_instance, tab_helper,
                                  segment.context.path),
        'order':
        segment.order,
        'source':
        get_source_object_info(segment),
        'dest':
        get_dest_object_info(segment),
        'translationProgress':
        get_translation_progress(segment, translation.target_locale),
    } for segment in related_object_segments]

    segments = string_segment_data + syncronised_value_segment_data + related_object_segment_data
    segments.sort(key=lambda segment: segment['order'])

    return render(
        request,
        'wagtail_localize/admin/edit_translation.html',
        {
            # These props are passed directly to the TranslationEditor react component
            'props':
            json.dumps(
                {
                    'object': {
                        'title':
                        str(instance),
                        'titleSegmentId':
                        title_segment_id,
                        'isLive':
                        is_live,
                        'isLocked':
                        is_locked,
                        'lastPublishedDate':
                        last_published_at.strftime(DATE_FORMAT)
                        if last_published_at is not None else None,
                        'lastPublishedBy':
                        UserSerializer(last_published_by).data
                        if last_published_by is not None else None,
                        'liveUrl':
                        live_url,
                    },
                    'breadcrumb':
                    breadcrumb,
                    'tabs':
                    tab_helper.tabs_with_slugs,
                    'sourceLocale': {
                        'code':
                        translation.source.locale.language_code,
                        'displayName':
                        translation.source.locale.get_display_name(),
                    },
                    'locale': {
                        'code':
                        translation.target_locale.language_code,
                        'displayName':
                        translation.target_locale.get_display_name(),
                    },
                    'translations': [{
                        'title':
                        str(translated_instance),
                        'locale': {
                            'code':
                            translated_instance.locale.language_code,
                            'displayName':
                            translated_instance.locale.get_display_name(),
                        },
                        'editUrl':
                        reverse('wagtailadmin_pages:edit',
                                args=[translated_instance.id]) if isinstance(
                                    translated_instance, Page) else
                        reverse('wagtailsnippets:edit',
                                args=[
                                    translated_instance._meta.app_label,
                                    translated_instance._meta.model_name,
                                    quote(translated_instance.id)
                                ]),
                    } for translated_instance in instance.get_translations().
                                     select_related('locale')],
                    'perms': {
                        'canPublish': can_publish,
                        'canUnpublish': can_unpublish,
                        'canLock': can_lock,
                        'canUnlock': can_unlock,
                        'canDelete': can_delete,
                    },
                    'links': {
                        'downloadPofile':
                        reverse('wagtail_localize:download_pofile',
                                args=[translation.id]),
                        'uploadPofile':
                        reverse('wagtail_localize:upload_pofile',
                                args=[translation.id]),
                        'unpublishUrl':
                        reverse('wagtailadmin_pages:unpublish',
                                args=[instance.id]) if isinstance(
                                    instance, Page) else None,
                        'lockUrl':
                        reverse('wagtailadmin_pages:lock', args=[instance.id])
                        if isinstance(instance, Page) else None,
                        'unlockUrl':
                        reverse('wagtailadmin_pages:unlock',
                                args=[instance.id]) if isinstance(
                                    instance, Page) else None,
                        'deleteUrl':
                        reverse('wagtailadmin_pages:delete',
                                args=[instance.id]) if isinstance(
                                    instance, Page) else reverse(
                                        'wagtailsnippets:delete',
                                        args=[
                                            instance._meta.app_label,
                                            instance._meta.model_name,
                                            quote(instance.pk)
                                        ]),
                        'stopTranslationUrl':
                        reverse('wagtail_localize:stop_translation',
                                args=[translation.id]),
                    },
                    'previewModes': [{
                        'mode':
                        mode,
                        'label':
                        label,
                        'url':
                        reverse('wagtail_localize:preview_translation',
                                args=[translation.id])
                        if mode == instance.default_preview_mode else reverse(
                            'wagtail_localize:preview_translation',
                            args=[translation.id, mode]),
                    } for mode, label in (instance.preview_modes if isinstance(
                        instance, Page) else [])],
                    'machineTranslator':
                    machine_translator,
                    'segments':
                    segments,

                    # We serialize the translation data using Django REST Framework.
                    # This gives us a consistent representation with the APIs so we
                    # can dynamically update translations in the view.
                    'initialStringTranslations':
                    StringTranslationSerializer(string_translations,
                                                many=True,
                                                context={
                                                    'translation_source':
                                                    translation.source
                                                }).data,
                    'initialOverrides':
                    SegmentOverrideSerializer(segment_overrides,
                                              many=True,
                                              context={
                                                  'translation_source':
                                                  translation.source
                                              }).data,
                },
                cls=DjangoJSONEncoder)
        })
Example #29
0
    def form_valid(self, form):
        response = super().form_valid(form)
        # Create the student account
        student_group = Group.objects.get(name="Students")
        student_user = User.objects.create_user(
            username=form.cleaned_data["username"],
            email=form.cleaned_data["email"],
            first_name=form.cleaned_data["first_name"],
            last_name=form.cleaned_data["last_name"],
        )
        # Add the student group
        student_user.groups.add(student_group)
        student_user.set_unusable_password()
        student_user.save()

        # return here if we aren't creating a page for the student
        if not form.cleaned_data["create_student_page"]:
            messages.success(
                self.request,
                f"The Student account for {student_user} has been created.",
            )
            return response

        # Is there a student index page we can create a student page under?
        student_index = StudentIndexPage.objects.first()
        if not student_index:
            messages.warning(
                self.request,
                f"Failed to create a Student Page matching for the new user: {student_user}, "
                "a Parent Student Index Page is required.",
            )
            logger.info(
                "There is not parent Student Index page to create a Student Page under, "
                f"so one has not been created for user: {student_user}")
            return response

        # If a student page already exist for this user, we don't want to create one.
        student_page = StudentPage.objects.filter(
            first_name=form.cleaned_data["first_name"],
            last_name=form.cleaned_data["last_name"],
        ).exists()

        if student_page:
            messages.success(
                self.request,
                f"The Student account for {student_user} has been created.",
            )
            messages.warning(
                self.request,
                f"Failed to create a Student Page matching for the new user: {student_user}, "
                "a Student Page already already exists",
            )
            logger.info(
                "A Student User has been created, but a StudentPage matching "
                f"the users name already exists: {student_page}, so one has not been created"
            )
        else:
            student_index.add_child(instance=StudentPage(
                first_name=form.cleaned_data["first_name"],
                last_name=form.cleaned_data["last_name"],
                title=
                f"{form.cleaned_data['first_name']} {form.cleaned_data['last_name']}",
                student_user_image_collection=form.
                cleaned_data["student_user_image_collection"],
                student_user_account=student_user,
                live=True,
            ))
            # Place the page in draft mode
            # StudentPage.save() handles the creation of the group and permissions for the student
            student_page = StudentPage.objects.get(
                student_user_account=student_user)
            student_page.save_revision()
            student_page.unpublish()

            # Generate a password reset link to be emailed to the user.
            password_reset_url = self.request.build_absolute_uri(
                get_set_password_url(student_user))
            # Notify the user of the account.
            email_subject = _("Your Student account has been created")
            email_body = render_to_string(
                "account_management/admin/emails/notify_user_on_creation.txt",
                {
                    "finish_registration_url":
                    password_reset_url,
                    "user":
                    student_user,
                    "PASSWORD_RESET_TIMEOUT_DAYS":
                    settings.PASSWORD_RESET_TIMEOUT_DAYS,
                },
            )
            try:
                user_notification_sent = send_mail(
                    email_subject,
                    email_body,
                    "*****@*****.**",
                    [student_user.email],
                )
            except SMTPException:
                logger.info(f"Failed to send email to new user {student_user}")
                messages.warning(
                    self.request,
                    f"The Student Page for {student_user} has been created. "
                    f"A notification email failed to send to {student_user.email}. ",
                    "Please contanct the site administrator.",
                )
                return response
            else:
                if user_notification_sent:
                    messages.success(
                        self.request,
                        f"The Student Page for {student_user} has been created. "
                        f"A notification email has been sent to {student_user.email}",
                    )
        return response
Example #30
0
def revisions_revert(request, page_id, revision_id):
    page = get_object_or_404(Page, id=page_id).specific
    page_perms = page.permissions_for_user(request.user)
    if not page_perms.can_edit():
        raise PermissionDenied

    revision = get_object_or_404(page.revisions, id=revision_id)
    revision_page = revision.as_object()

    content_type = ContentType.objects.get_for_model(page)
    page_class = content_type.model_class()

    edit_handler = page_class.get_edit_handler()
    form_class = edit_handler.get_form_class()

    form = form_class(instance=revision_page)
    edit_handler = edit_handler.get_bound_panel(instance=revision_page,
                                                request=request,
                                                form=form)

    lock = page.get_lock()

    action_menu = PageActionMenu(
        request,
        view="revisions_revert",
        page=page,
        lock=lock,
        locked_for_user=lock is not None and lock.for_user(request.user),
    )
    side_panels = PageSidePanels(
        request,
        page,
        preview_enabled=True,
        comments_enabled=form.show_comments_toggle,
    )

    user_avatar = render_to_string("wagtailadmin/shared/user_avatar.html",
                                   {"user": revision.user})

    messages.warning(
        request,
        mark_safe(
            _("You are viewing a previous version of this page from <b>%(created_at)s</b> by %(user)s"
              ) % {
                  "created_at": revision.created_at.strftime("%d %b %Y %H:%M"),
                  "user": user_avatar,
              }),
    )

    return TemplateResponse(
        request,
        "wagtailadmin/pages/edit.html",
        {
            "page":
            page,
            "revision":
            revision,
            "is_revision":
            True,
            "content_type":
            content_type,
            "edit_handler":
            edit_handler,
            "errors_debug":
            None,
            "action_menu":
            action_menu,
            "side_panels":
            side_panels,
            "form":
            form,  # Used in unit tests
            "media":
            edit_handler.media + form.media + action_menu.media +
            side_panels.media,
        },
    )
Example #31
0
def publish(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_publish():
        raise PermissionDenied

    next_url = pages.get_valid_next_url_from_request(request)

    if request.method == 'POST':

        page.get_latest_revision().publish()

        # TODO: clean up copypasta when coa-publisher phases out previously AWS publish pipeline
        # Show success message if there is a publish_janis_branch set (for netlify builds)
        # Or default to show success message on Staging and Production (follow existing AWS implementation pattern)
        try:
            publish_janis_branch = getattr(JanisBranchSettings.objects.first(),
                                           'publish_janis_branch')
        except:
            publish_janis_branch = None
        if settings.ISSTAGING or settings.ISPRODUCTION:
            messages.success(request,
                             _("Page '{0}' published.").format(
                                 page.get_admin_display_title()),
                             buttons=[
                                 messages.button(
                                     reverse('wagtailadmin_pages:edit',
                                             args=(page.id, )), _('Edit'))
                             ])
        elif settings.ISLOCAL:
            messages.warning(
                request,
                _("Page '{0}' not published. You're running on a local environment."
                  ).format(page.get_admin_display_title()),
                buttons=[
                    messages.button(
                        reverse('wagtailadmin_pages:edit', args=(page.id, )),
                        _('Edit'))
                ])
        elif publish_janis_branch:
            messages.success(request,
                             _("Page '{0}' published.").format(
                                 page.get_admin_display_title()),
                             buttons=[
                                 messages.button(
                                     reverse('wagtailadmin_pages:edit',
                                             args=(page.id, )), _('Edit'))
                             ])
        else:
            messages.warning(
                request,
                _("Page '{0}' not published. No `publish_janis_branch` was set."
                  ).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 redirect('/admin/pages/search/')

    return render(request, 'wagtailadmin/pages/confirm_publish.html', {
        'page': page,
        'next': next_url,
    })