Add site switcher to header in settings

pull/1754/head
Tim Heap 2015-10-21 16:31:13 +11:00
rodzic 72c81e8317
commit 5d81269548
8 zmienionych plików z 176 dodań i 35 usunięć

Wyświetl plik

@ -55,6 +55,7 @@ var apps = [
'wagtailstyleguide/scss/styleguide.scss' 'wagtailstyleguide/scss/styleguide.scss'
], ],
}), }),
new App('wagtail/contrib/settings'),
]; ];
module.exports = { module.exports = {

Wyświetl plik

@ -0,0 +1 @@
static/

Wyświetl plik

@ -0,0 +1,27 @@
from __future__ import absolute_import, unicode_literals
from django import forms
from django.core.urlresolvers import reverse
from wagtail.wagtailcore.models import Site
class SiteSwitchForm(forms.Form):
site = forms.ChoiceField(choices=[])
class Media:
js = [
'settings/js/site-switcher.js',
]
def __init__(self, current_site, model, **kwargs):
initial_data = {'site': self.get_change_url(current_site, model)}
super(SiteSwitchForm, self).__init__(initial=initial_data, **kwargs)
sites = [(self.get_change_url(site, model), site)
for site in Site.objects.all()]
self.fields['site'].choices = sites
@classmethod
def get_change_url(cls, site, model):
return reverse('wagtailsettings_edit', args=[
site.pk, model._meta.app_label, model._meta.model_name])

Wyświetl plik

@ -0,0 +1,12 @@
$(function() {
var $switcher = $('form#settings-site-switch select');
if (!$switcher.length) return;
var initial = $switcher.val();
$switcher.on('change', function() {
var url = $switcher.val();
if (url != initial) {
window.location = url;
}
});
});

Wyświetl plik

@ -3,10 +3,30 @@
{% block titletag %}{% blocktrans %}Editing {{ setting_type_name}} - {{ instance }}{% endblocktrans %}{% endblock %} {% block titletag %}{% blocktrans %}Editing {{ setting_type_name}} - {{ instance }}{% endblocktrans %}{% endblock %}
{% block bodyclass %}menu-settings{% endblock %} {% block bodyclass %}menu-settings{% endblock %}
{% block content %} {% block content %}
{% trans "Editing" as editing_str %} <header class="nice-padding">
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=setting_type_name|capfirst icon="cogs" %} <div class="row">
<div class="left">
<div class="col">
<h1 class="icon icon-cogs">
{% trans "Editing" %}
<span>{{ setting_type_name|capfirst }}</span>
</h1>
</div>
</div>
<div class="right">
{% if site_switcher %}
<form method="get" id="settings-site-switch">
<label for="{{ site_switcher.site.id_for_label }}">
Site:
</label>
{{ site_switcher.site }}
</form>
{% endif %}
</div>
</div>
</header>
<form action="{% url 'wagtailsettings_edit' opts.app_label opts.model_name %}" method="POST"> <form action="{% url 'wagtailsettings_edit' site.pk opts.app_label opts.model_name %}" method="POST">
{% csrf_token %} {% csrf_token %}
{{ edit_handler.render_form_content }} {{ edit_handler.render_form_content }}
@ -23,7 +43,11 @@
{% block extra_css %} {% block extra_css %}
{% include "wagtailadmin/pages/_editor_css.html" %} {% include "wagtailadmin/pages/_editor_css.html" %}
{{ form.media.css }}
{{ site_switcher.media.css }}
{% endblock %} {% endblock %}
{% block extra_js %} {% block extra_js %}
{% include "wagtailadmin/pages/_editor_js.html" %} {% include "wagtailadmin/pages/_editor_js.html" %}
{{ form.media.js }}
{{ site_switcher.media.js }}
{% endblock %} {% endblock %}

Wyświetl plik

@ -1,3 +1,5 @@
from __future__ import absolute_import, unicode_literals
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -8,7 +10,7 @@ from wagtail.contrib.settings.registry import SettingMenuItem
from wagtail.tests.testapp.models import IconSetting, TestSetting from wagtail.tests.testapp.models import IconSetting, TestSetting
from wagtail.tests.utils import WagtailTestUtils from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailcore import hooks from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Site from wagtail.wagtailcore.models import Page, Site
class TestSettingMenu(TestCase, WagtailTestUtils): class TestSettingMenu(TestCase, WagtailTestUtils):
@ -42,20 +44,23 @@ class TestSettingMenu(TestCase, WagtailTestUtils):
self.assertEqual(classnames, {'icon', 'icon-tag', 'test-class'}) self.assertEqual(classnames, {'icon', 'icon-tag', 'test-class'})
class TestSettingCreateView(TestCase, WagtailTestUtils): class BaseTestSettingView(TestCase, WagtailTestUtils):
def get(self, site_pk=1, params={}):
url = self.edit_url('tests', 'testsetting', site_pk=site_pk)
return self.client.get(url, params)
def post(self, site_pk=1, post_data={}):
url = self.edit_url('tests', 'testsetting', site_pk=site_pk)
return self.client.post(url, post_data)
def edit_url(self, app, model, site_pk=1):
return reverse('wagtailsettings_edit', args=[site_pk, app, model])
class TestSettingCreateView(BaseTestSettingView):
def setUp(self): def setUp(self):
self.login() self.login()
def get(self, params={}):
return self.client.get(
reverse('wagtailsettings_edit', args=('tests', 'testsetting')),
params)
def post(self, post_data={}):
return self.client.post(
reverse('wagtailsettings_edit', args=('tests', 'testsetting')),
post_data)
def test_status_code(self): def test_status_code(self):
self.assertEqual(self.get().status_code, 200) self.assertEqual(self.get().status_code, 200)
@ -75,7 +80,7 @@ class TestSettingCreateView(TestCase, WagtailTestUtils):
self.assertEqual(setting.email, 'test@example.com') self.assertEqual(setting.email, 'test@example.com')
class TestSettingEditView(TestCase, WagtailTestUtils): class TestSettingEditView(BaseTestSettingView):
def setUp(self): def setUp(self):
default_site = Site.objects.get(is_default_site=True) default_site = Site.objects.get(is_default_site=True)
@ -87,22 +92,11 @@ class TestSettingEditView(TestCase, WagtailTestUtils):
self.login() self.login()
def get(self, params={}):
return self.client.get(
reverse('wagtailsettings_edit', args=('tests', 'testsetting')),
params)
def post(self, post_data={}):
return self.client.post(
reverse('wagtailsettings_edit', args=('tests', 'testsetting')),
post_data)
def test_status_code(self): def test_status_code(self):
self.assertEqual(self.get().status_code, 200) self.assertEqual(self.get().status_code, 200)
def test_non_existant_model(self): def test_non_existant_model(self):
response = self.client.get( response = self.client.get(self.edit_url('test', 'foo'))
reverse('wagtailsettings_edit', args=('tests', 'foo')))
self.assertEqual(response.status_code, 404) self.assertEqual(response.status_code, 404)
def test_edit_invalid(self): def test_edit_invalid(self):
@ -121,6 +115,74 @@ class TestSettingEditView(TestCase, WagtailTestUtils):
self.assertEqual(setting.email, 'test@example.com') self.assertEqual(setting.email, 'test@example.com')
class TestMultiSite(BaseTestSettingView):
def setUp(self):
self.default_site = Site.objects.get(is_default_site=True)
self.other_site = Site.objects.create(hostname='example.com', root_page=Page.objects.get(pk=2))
self.login()
def test_redirect_to_default(self):
"""
Should redirect to the setting for the default site.
"""
start_url = reverse('wagtailsettings_edit', args=[
'tests', 'testsetting'])
dest_url = 'http://testserver' + reverse('wagtailsettings_edit', args=[
self.default_site.pk, 'tests', 'testsetting'])
response = self.client.get(start_url, follow=True)
self.assertEqual([(dest_url, 302)], response.redirect_chain)
def test_redirect_to_current(self):
"""
Should redirect to the setting for the current site taken from the URL,
by default
"""
start_url = reverse('wagtailsettings_edit', args=[
'tests', 'testsetting'])
dest_url = 'http://example.com' + reverse('wagtailsettings_edit', args=[
self.other_site.pk, 'tests', 'testsetting'])
response = self.client.get(start_url, follow=True, HTTP_HOST=self.other_site.hostname)
self.assertEqual([(dest_url, 302)], response.redirect_chain)
def test_switcher(self):
""" Check that the switcher form exists in the page """
response = self.get()
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'id="settings-site-switch"')
def test_unknown_site(self):
""" Check that unknown sites throw a 404 """
response = self.get(site_pk=3)
self.assertEqual(response.status_code, 404)
def test_edit(self):
"""
Check that editing settings in multi-site mode edits the correct
setting, and leaves the other ones alone
"""
TestSetting.objects.create(
title='default',
email='default@example.com',
site=self.default_site)
TestSetting.objects.create(
title='other',
email='other@example.com',
site=self.other_site)
response = self.post(site_pk=self.other_site.pk, post_data={
'title': 'other-new', 'email': 'other-other@example.com'})
self.assertEqual(response.status_code, 302)
# Check that the correct setting was updated
other_setting = TestSetting.for_site(self.other_site)
self.assertEqual(other_setting.title, 'other-new')
self.assertEqual(other_setting.email, 'other-other@example.com')
# Check that the other setting was not updated
default_setting = TestSetting.for_site(self.default_site)
self.assertEqual(default_setting.title, 'default')
self.assertEqual(default_setting.email, 'default@example.com')
class TestAdminPermission(TestCase, WagtailTestUtils): class TestAdminPermission(TestCase, WagtailTestUtils):
def test_registered_permission(self): def test_registered_permission(self):
permission = Permission.objects.get_by_natural_key( permission = Permission.objects.get_by_natural_key(

Wyświetl plik

@ -3,5 +3,6 @@ from django.conf.urls import url
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^(\w+)/(\w+)/$', views.edit, name='wagtailsettings_edit'), url(r'^(\w+)/(\w+)/$', views.edit_current_site, name='wagtailsettings_edit'),
url(r'^(\d+)/(\w+)/(\w+)/$', views.edit, name='wagtailsettings_edit'),
] ]

Wyświetl plik

@ -1,7 +1,6 @@
from django.contrib.auth.decorators import permission_required
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http import Http404 from django.http import Http404
from django.shortcuts import redirect, render from django.shortcuts import redirect, render, get_object_or_404
from django.utils.lru_cache import lru_cache from django.utils.lru_cache import lru_cache
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -9,7 +8,9 @@ from django.utils.translation import ugettext as _
from wagtail.wagtailadmin import messages from wagtail.wagtailadmin import messages
from wagtail.wagtailadmin.edit_handlers import ( from wagtail.wagtailadmin.edit_handlers import (
ObjectList, extract_panel_definitions_from_model_class) ObjectList, extract_panel_definitions_from_model_class)
from wagtail.wagtailcore.models import Site
from .forms import SiteSwitchForm
from .permissions import user_can_edit_setting_type from .permissions import user_can_edit_setting_type
from .registry import registry from .registry import registry
@ -31,15 +32,20 @@ def get_setting_edit_handler(model):
return ObjectList(panels).bind_to_model(model) return ObjectList(panels).bind_to_model(model)
@permission_required('wagtailadmin.access_admin') # further permissions are enforced within the view def edit_current_site(request, app_name, model_name):
def edit(request, app_name, model_name): # Redirect the user to the edit page for the current site
return redirect('wagtailsettings_edit', request.site.pk, app_name, model_name)
def edit(request, site_pk, app_name, model_name):
model = get_model_from_url_params(app_name, model_name) model = get_model_from_url_params(app_name, model_name)
if not user_can_edit_setting_type(request.user, model): if not user_can_edit_setting_type(request.user, model):
raise PermissionDenied raise PermissionDenied
site = get_object_or_404(Site, pk=site_pk)
setting_type_name = model._meta.verbose_name setting_type_name = model._meta.verbose_name
instance = model.for_site(request.site) instance = model.for_site(site)
edit_handler_class = get_setting_edit_handler(model) edit_handler_class = get_setting_edit_handler(model)
form_class = edit_handler_class.get_form_class(model) form_class = edit_handler_class.get_form_class(model)
@ -56,7 +62,7 @@ def edit(request, app_name, model_name):
instance=instance instance=instance
) )
) )
return redirect('wagtailsettings_edit', app_name, model_name) return redirect('wagtailsettings_edit', site.pk, app_name, model_name)
else: else:
messages.error(request, _("The setting could not be saved due to errors.")) messages.error(request, _("The setting could not be saved due to errors."))
edit_handler = edit_handler_class(instance=instance, form=form) edit_handler = edit_handler_class(instance=instance, form=form)
@ -64,9 +70,16 @@ def edit(request, app_name, model_name):
form = form_class(instance=instance) form = form_class(instance=instance)
edit_handler = edit_handler_class(instance=instance, form=form) edit_handler = edit_handler_class(instance=instance, form=form)
# Show a site switcher form if there are multiple sites
site_switcher = None
if Site.objects.count() > 1:
site_switcher = SiteSwitchForm(site, model)
return render(request, 'wagtailsettings/edit.html', { return render(request, 'wagtailsettings/edit.html', {
'opts': model._meta, 'opts': model._meta,
'setting_type_name': setting_type_name, 'setting_type_name': setting_type_name,
'instance': instance, 'instance': instance,
'edit_handler': edit_handler, 'edit_handler': edit_handler,
'site': site,
'site_switcher': site_switcher,
}) })