Merge branch 'master' into form-builder

Conflicts:
	wagtail/wagtailadmin/templatetags/wagtailadmin_tags.py
This commit is contained in:
Matt Westcott 2014-04-28 17:33:06 +01:00
commit 71e45dee23
12 changed files with 182 additions and 36 deletions

View file

@ -319,7 +319,7 @@ $(function() {
});
/* Set up behaviour of preview button */
$('#action-preview').click(function() {
$('.action-preview').click(function() {
var previewWindow = window.open($(this).data('placeholder'), $(this).data('windowname'));
$.ajax({

View file

@ -0,0 +1,4 @@
<input type="button" class="action-preview button"
data-action="{% url 'wagtailadmin_pages_preview_on_create' content_type.app_label content_type.model parent_page.id %}{% if mode %}?mode={{ mode|urlencode }}{% endif %}"
data-placeholder="{% url 'wagtailadmin_pages_preview_placeholder' %}"
data-windowname="wagtail_preview_{{ parent_page.id }}_child" value="{{ label }}" />

View file

@ -0,0 +1,4 @@
<input type="button" class="action-preview button"
data-action="{% url 'wagtailadmin_pages_preview_on_edit' page.id %}{% if mode %}?mode={{ mode|urlencode }}{% endif %}"
data-placeholder="{% url 'wagtailadmin_pages_preview_placeholder' %}"
data-windowname="wagtail_preview_{{ page.id }}" value="{{ label }}" />

View file

@ -29,7 +29,6 @@
<input type="submit" value="{% trans 'Save as draft' %}" class="button" />
<div class="dropdown-toggle icon icon-arrow-up"></div>
<ul role="menu">
<li><input type="button" id="action-preview" data-action="{% url 'wagtailadmin_pages_preview_on_create' content_type.app_label content_type.model parent_page.id %}" data-placeholder="{% url 'wagtailadmin_pages_preview_placeholder' %}" data-windowname="wagtail_preview_{{ parent_page.id }}_child" value="{% trans 'Preview' %}" class="button" /></li>
{% if parent_page_perms.can_publish_subpage %}
<li><input type="submit" name="action-publish" value="{% trans 'Publish' %}" class="button" /></li>
{% endif %}
@ -37,6 +36,25 @@
</ul>
</div>
</li>
<li class="actions">
{% trans 'Preview' as preview_label %}
{% if display_modes|length > 1 %}
<div class="dropdown dropup match-width">
{% include "wagtailadmin/pages/_preview_button_on_create.html" with label=preview_label %}
<div class="dropdown-toggle icon icon-arrow-up"></div>
<ul role="menu">
{% for mode_name, mode_display_name in display_modes %}
<li>
{% include "wagtailadmin/pages/_preview_button_on_create.html" with mode=mode_name label=mode_display_name %}
</li>
{% endfor %}
</ul>
</div>
{% else %}
{% include "wagtailadmin/pages/_preview_button_on_create.html" with label=preview_label %}
{% endif %}
</li>
</ul>
</footer>
</form>

View file

@ -41,13 +41,29 @@
<li><input type="submit" name="action-publish" value="{% trans 'Publish' %}" class="button" /></li>
{% endif %}
<li><input type="submit" name="action-submit" value="{% trans 'Submit for moderation' %}" class="button" /></li>
<li><input type="button" id="action-preview" data-action="{% url 'wagtailadmin_pages_preview_on_edit' page.id %}" data-placeholder="{% url 'wagtailadmin_pages_preview_placeholder' %}" data-windowname="wagtail_preview_{{ page.id }}" value="{% trans 'Preview' %}" class="button" /></li>
</ul>
</div>
</li>
<li class="notices">
<li class="actions">
{% trans 'Preview' as preview_label %}
{% if display_modes|length > 1 %}
<div class="dropdown dropup match-width">
{% include "wagtailadmin/pages/_preview_button_on_edit.html" with label=preview_label %}
<div class="dropdown-toggle icon icon-arrow-up"></div>
<ul role="menu">
{% for mode_name, mode_display_name in display_modes %}
<li>
{% include "wagtailadmin/pages/_preview_button_on_edit.html" with mode=mode_name label=mode_display_name %}
</li>
{% endfor %}
</ul>
</div>
{% else %}
{% include "wagtailadmin/pages/_preview_button_on_edit.html" with label=preview_label %}
{% endif %}
</li>
<li class="meta">
<p class="modified">
{% if page.get_latest_revision %}

View file

@ -9,7 +9,6 @@ from wagtail.wagtailcore.models import get_navigation_menu_items, UserPagePermis
from wagtail.wagtailcore.util import camelcase_to_underscore
from wagtail.wagtailforms.models import get_form_types
from wagtail.wagtailsnippets.permissions import user_can_edit_snippets # TODO: reorganise into pluggable architecture so that wagtailsnippets registers its own menu item
register = template.Library()
@ -47,26 +46,6 @@ def main_nav(context):
]
request = context['request']
user = request.user
if user.has_perm('wagtailimages.add_image'):
menu_items.append(
MenuItem(_('Images'), urlresolvers.reverse('wagtailimages_index'), classnames='icon icon-image', order=300)
)
if user.has_perm('wagtaildocs.add_document'):
menu_items.append(
MenuItem(_('Documents'), urlresolvers.reverse('wagtaildocs_index'), classnames='icon icon-doc-full-inverse', order=400)
)
if user_can_edit_snippets(user):
menu_items.append(
MenuItem(_('Snippets'), urlresolvers.reverse('wagtailsnippets_index'), classnames='icon icon-snippet', order=500)
)
if user.has_module_perms('auth'):
menu_items.append(
MenuItem(_('Users'), urlresolvers.reverse('wagtailusers_index'), classnames='icon icon-user', order=600)
)
if get_form_types(): # show this only if forms actually exist
menu_items.append(

View file

@ -1,8 +1,6 @@
from django.http import Http404, HttpResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.core.exceptions import ValidationError, PermissionDenied
from django.template.loader import render_to_string
from django.template import RequestContext
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.decorators import permission_required
@ -210,6 +208,7 @@ def create(request, content_type_app_name, content_type_model_name, parent_page_
'page_class': page_class,
'parent_page': parent_page,
'edit_handler': edit_handler,
'display_modes': page.get_page_modes(),
})
@ -294,6 +293,7 @@ def edit(request, page_id):
'page': page,
'edit_handler': edit_handler,
'errors_debug': errors_debug,
'display_modes': page.get_page_modes(),
})
@ -340,12 +340,19 @@ def preview_on_edit(request, page_id):
if form.is_valid():
form.save(commit=False)
# FIXME: passing the original request to page.serve is dodgy (particularly if page.serve has
# special treatment of POSTs). Ought to construct one that more or less matches what would be sent
# as a front-end GET request
# This view will generally be invoked as an AJAX request; as such, in the case of
# an error Django will return a plaintext response. This isn't what we want, since
# we will be writing the response back to an HTML page regardless of success or
# failure - as such, we strip out the X-Requested-With header to get Django to return
# an HTML error response
request.META.pop('HTTP_X_REQUESTED_WITH', None)
request.META.pop('HTTP_X_REQUESTED_WITH', None) # Make this request appear to the page's serve method as a non-ajax one, as they will often implement custom behaviour for XHR
response = page.serve(request)
try:
display_mode = request.GET['mode']
except KeyError:
display_mode = page.get_page_modes()[0][0]
response = page.show_as_mode(display_mode)
response['X-Wagtail-Preview'] = 'ok'
return response
@ -356,6 +363,7 @@ def preview_on_edit(request, page_id):
response = render(request, 'wagtailadmin/pages/edit.html', {
'page': page,
'edit_handler': edit_handler,
'display_modes': page.get_page_modes(),
})
response['X-Wagtail-Preview'] = 'error'
return response
@ -380,10 +388,18 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p
if form.is_valid():
form.save(commit=False)
# FIXME: passing the original request to page.serve is dodgy (particularly if page.serve has
# special treatment of POSTs). Ought to construct one that more or less matches what would be sent
# as a front-end GET request
response = page.serve(request)
# This view will generally be invoked as an AJAX request; as such, in the case of
# an error Django will return a plaintext response. This isn't what we want, since
# we will be writing the response back to an HTML page regardless of success or
# failure - as such, we strip out the X-Requested-With header to get Django to return
# an HTML error response
request.META.pop('HTTP_X_REQUESTED_WITH', None)
try:
display_mode = request.GET['mode']
except KeyError:
display_mode = page.get_page_modes()[0][0]
response = page.show_as_mode(display_mode)
response['X-Wagtail-Preview'] = 'ok'
return response
@ -397,6 +413,7 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p
'page_class': page_class,
'parent_page': parent_page,
'edit_handler': edit_handler,
'display_modes': page.get_page_modes(),
})
response['X-Wagtail-Preview'] = 'error'
return response

View file

@ -1,5 +1,7 @@
import sys
import os
from StringIO import StringIO
from urlparse import urlparse
from modelcluster.models import ClusterableModel
@ -7,6 +9,8 @@ from django.db import models, connection, transaction
from django.db.models import get_model, Q
from django.http import Http404
from django.core.cache import cache
from django.core.handlers.wsgi import WSGIRequest
from django.core.handlers.base import BaseHandler
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Group
from django.conf import settings
@ -552,6 +556,61 @@ class Page(MP_Node, ClusterableModel, Indexed):
user_perms = UserPagePermissionsProxy(user)
return user_perms.for_page(self)
def dummy_request(self):
"""
Construct a HttpRequest object that is, as far as possible, representative of ones that would
receive this page as a response. Used for previewing / moderation and any other place where we
want to display a view of this page in the admin interface without going through the regular
page routing logic.
"""
url = self.full_url
if url:
url_info = urlparse(url)
hostname = url_info.netloc
path = url_info.path
port = url_info.port or 80
else:
hostname = 'example.com'
path = '/'
port = 80
request = WSGIRequest({
'REQUEST_METHOD': 'GET',
'PATH_INFO': path,
'SERVER_NAME': hostname,
'SERVER_PORT': port,
'wsgi.input': StringIO(),
})
# Apply middleware to the request - see http://www.mellowmorning.com/2011/04/18/mock-django-request-for-testing/
handler = BaseHandler()
handler.load_middleware()
for middleware_method in handler._request_middleware:
if middleware_method(request):
raise Exception("Couldn't create request mock object - "
"request middleware returned a response")
return request
def get_page_modes(self):
"""
Return a list of (internal_name, display_name) tuples for the modes in which
this page can be displayed for preview/moderation purposes. Ordinarily a page
will only have one display mode, but subclasses of Page can override this -
for example, a page containing a form might have a default view of the form,
and a post-submission 'thankyou' page
"""
return [('', 'Default')]
def show_as_mode(self, mode_name):
"""
Given an internal name from the get_page_modes() list, return an HTTP response
indicative of the page being viewed in that mode. By default this passes a
dummy request into the serve() mechanism, ensuring that it matches the behaviour
on the front-end; subclasses that define additional page modes will need to
implement alternative logic to serve up the appropriate view here.
"""
return self.serve(self.dummy_request())
def get_ancestors(self, inclusive=False):
return Page.objects.ancestor_of(self, inclusive)

View file

@ -1,6 +1,10 @@
from django.conf.urls import include, url
from django.core import urlresolvers
from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin import hooks
from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtaildocs import admin_urls
@ -9,3 +13,11 @@ def register_admin_urls():
url(r'^documents/', include(admin_urls)),
]
hooks.register('register_admin_urls', register_admin_urls)
def construct_main_menu(request, menu_items):
if request.user.has_perm('wagtaildocs.add_document'):
menu_items.append(
MenuItem(_('Documents'), urlresolvers.reverse('wagtaildocs_index'), classnames='icon icon-doc-full-inverse', order=400)
)
hooks.register('construct_main_menu', construct_main_menu)

View file

@ -1,6 +1,10 @@
from django.conf.urls import include, url
from django.core import urlresolvers
from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin import hooks
from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtailimages import urls
@ -9,3 +13,11 @@ def register_admin_urls():
url(r'^images/', include(urls)),
]
hooks.register('register_admin_urls', register_admin_urls)
def construct_main_menu(request, menu_items):
if request.user.has_perm('wagtailimages.add_image'):
menu_items.append(
MenuItem(_('Images'), urlresolvers.reverse('wagtailimages_index'), classnames='icon icon-image', order=300)
)
hooks.register('construct_main_menu', construct_main_menu)

View file

@ -1,7 +1,12 @@
from django.conf.urls import include, url
from django.core import urlresolvers
from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin import hooks
from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtailsnippets import urls
from wagtail.wagtailsnippets.permissions import user_can_edit_snippets
def register_admin_urls():
@ -9,3 +14,11 @@ def register_admin_urls():
url(r'^snippets/', include(urls)),
]
hooks.register('register_admin_urls', register_admin_urls)
def construct_main_menu(request, menu_items):
if user_can_edit_snippets(request.user):
menu_items.append(
MenuItem(_('Snippets'), urlresolvers.reverse('wagtailsnippets_index'), classnames='icon icon-snippet', order=500)
)
hooks.register('construct_main_menu', construct_main_menu)

View file

@ -1,6 +1,10 @@
from django.conf.urls import include, url
from django.core import urlresolvers
from django.utils.translation import ugettext_lazy as _
from wagtail.wagtailadmin import hooks
from wagtail.wagtailadmin.menu import MenuItem
from wagtail.wagtailusers import urls
@ -9,3 +13,11 @@ def register_admin_urls():
url(r'^users/', include(urls)),
]
hooks.register('register_admin_urls', register_admin_urls)
def construct_main_menu(request, menu_items):
if request.user.has_module_perms('auth'):
menu_items.append(
MenuItem(_('Users'), urlresolvers.reverse('wagtailusers_index'), classnames='icon icon-user', order=600)
)
hooks.register('construct_main_menu', construct_main_menu)