diff --git a/bakerydemo/settings/base.py b/bakerydemo/settings/base.py
index d30a24f..c0b7bcb 100644
--- a/bakerydemo/settings/base.py
+++ b/bakerydemo/settings/base.py
@@ -58,6 +58,7 @@ INSTALLED_APPS = [
'wagtailfontawesome',
'wagtail_i18n',
'wagtail_i18n.plugins.sites',
+ 'wagtail_i18n.plugins.regions_admin',
'django.contrib.admin',
'django.contrib.auth',
diff --git a/wagtail_i18n/models.py b/wagtail_i18n/models.py
index 9640e28..5ffaaff 100644
--- a/wagtail_i18n/models.py
+++ b/wagtail_i18n/models.py
@@ -65,6 +65,9 @@ class Region(models.Model):
def default_id(cls):
return cls.default().id
+ def __str__(self):
+ return self.name
+
class TranslatableMixin(models.Model):
translation_key = models.UUIDField(default=uuid.uuid4, editable=False)
diff --git a/wagtail_i18n/plugins/regions_admin/__init__.py b/wagtail_i18n/plugins/regions_admin/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/wagtail_i18n/plugins/regions_admin/apps.py b/wagtail_i18n/plugins/regions_admin/apps.py
new file mode 100644
index 0000000..514449c
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/apps.py
@@ -0,0 +1,7 @@
+from django.apps import AppConfig
+
+
+class WagtailI18NRegionsAdminAppConfig(AppConfig):
+ label = 'wagtail_i18n_regions_admin'
+ name = 'wagtail_i18n.plugins.regions_admin'
+ verbose_name = "Wagtail I18N Regions admin"
diff --git a/wagtail_i18n/plugins/regions_admin/forms.py b/wagtail_i18n/plugins/regions_admin/forms.py
new file mode 100644
index 0000000..2f9a15c
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/forms.py
@@ -0,0 +1,15 @@
+from django import forms
+from django.utils.functional import cached_property
+from django.utils.translation import ugettext_lazy as _
+
+from wagtail.admin.widgets import AdminPageChooser
+
+from wagtail_i18n.models import Region
+
+
+class RegionForm(forms.ModelForm):
+ required_css_class = 'required'
+
+ class Meta:
+ model = Region
+ fields = ['name', 'slug', 'languages']
diff --git a/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/create.html b/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/create.html
new file mode 100644
index 0000000..872efee
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/create.html
@@ -0,0 +1,31 @@
+{% extends "wagtailadmin/generic/create.html" %}
+{% load i18n %}
+
+{% block content %}
+
+ {% include "wagtailadmin/shared/header.html" with title=view.page_title icon=view.header_icon %}
+
+
+{% endblock %}
+
+{% block extra_js %}
+ {{ block.super }}
+ {% include "wagtailadmin/pages/_editor_js.html" %}
+{% endblock %}
diff --git a/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/edit.html b/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/edit.html
new file mode 100644
index 0000000..e171fca
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/edit.html
@@ -0,0 +1,38 @@
+{% extends "wagtailadmin/generic/edit.html" %}
+{% load i18n %}
+
+{% block content %}
+
+ {% include "wagtailadmin/shared/header.html" with title=view.page_title subtitle=view.get_page_subtitle icon=view.header_icon %}
+
+
+ {% block before_form %}{% endblock %}
+
+
+{% endblock %}
+
+{% block extra_js %}
+ {{ block.super }}
+ {% include "wagtailadmin/pages/_editor_js.html" %}
+{% endblock %}
diff --git a/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/index.html b/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/index.html
new file mode 100644
index 0000000..cae10bf
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/templates/wagtail_i18n_regions_admin/index.html
@@ -0,0 +1,28 @@
+{% extends "wagtailadmin/generic/index.html" %}
+{% load i18n %}
+
+{% block listing %}
+
+
+
+
+
+ {% trans "Name" %} |
+
+
+
+ {% for region in regions %}
+
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+
+{% endblock %}
diff --git a/wagtail_i18n/plugins/regions_admin/views.py b/wagtail_i18n/plugins/regions_admin/views.py
new file mode 100644
index 0000000..bd65cdd
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/views.py
@@ -0,0 +1,50 @@
+from django.db import transaction
+from django.utils.translation import ugettext_lazy
+
+from wagtail.admin.views import generic
+from wagtail.admin.viewsets.model import ModelViewSet
+from wagtail.core.permission_policies import ModelPermissionPolicy
+
+from wagtail_i18n.models import Region
+from .forms import RegionForm
+
+
+class IndexView(generic.IndexView):
+ template_name = 'wagtail_i18n_regions_admin/index.html'
+ page_title = ugettext_lazy("Regions")
+ add_item_label = ugettext_lazy("Add a region")
+ context_object_name = 'regions'
+
+
+class CreateView(generic.CreateView):
+ page_title = ugettext_lazy("Add region")
+ success_message = ugettext_lazy("Region '{0}' created.")
+ template_name = 'wagtail_i18n_regions_admin/create.html'
+
+
+class EditView(generic.EditView):
+ success_message = ugettext_lazy("Region '{0}' updated.")
+ error_message = ugettext_lazy("The site could not be saved due to errors.")
+ delete_item_label = ugettext_lazy("Delete region")
+ context_object_name = 'region'
+ template_name = 'wagtail_i18n_regions_admin/edit.html'
+
+
+class DeleteView(generic.DeleteView):
+ success_message = ugettext_lazy("Region '{0}' deleted.")
+ page_title = ugettext_lazy("Delete region")
+ confirmation_message = ugettext_lazy("Are you sure you want to delete this region?")
+
+
+class RegionViewSet(ModelViewSet):
+ icon = 'site'
+ model = Region
+ permission_policy = ModelPermissionPolicy(Region)
+
+ index_view_class = IndexView
+ add_view_class = CreateView
+ edit_view_class = EditView
+ delete_view_class = DeleteView
+
+ def get_form_class(self, for_update=False):
+ return RegionForm
diff --git a/wagtail_i18n/plugins/regions_admin/wagtail_hooks.py b/wagtail_i18n/plugins/regions_admin/wagtail_hooks.py
new file mode 100644
index 0000000..2ea768b
--- /dev/null
+++ b/wagtail_i18n/plugins/regions_admin/wagtail_hooks.py
@@ -0,0 +1,34 @@
+from django.contrib.auth.models import Permission
+from django.urls import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from wagtail.admin.menu import MenuItem
+from wagtail.core import hooks
+from wagtail.core.permission_policies import ModelPermissionPolicy
+
+from wagtail_i18n.models import Region
+from .views import RegionViewSet
+
+
+@hooks.register('register_admin_viewset')
+def register_viewset():
+ return RegionViewSet('wagtail_i18n_regions_admin', url_prefix='i18nregions')
+
+
+class RegionsMenuItem(MenuItem):
+ def is_shown(self, request):
+ return ModelPermissionPolicy(Region).user_has_any_permission(
+ request.user, ['add', 'change', 'delete']
+ )
+
+
+@hooks.register('register_settings_menu_item')
+def register_sites_menu_item():
+ return RegionsMenuItem(_('Regions'), reverse('wagtail_i18n_regions_admin:index'),
+ classnames='icon icon-site', order=602)
+
+
+@hooks.register('register_permissions')
+def register_permissions():
+ return Permission.objects.filter(content_type__app_label='wagtail_i18n_regions_admin',
+ codename__in=['add_region', 'change_region', 'delete_region'])
diff --git a/wagtail_i18n/plugins/sites/forms.py b/wagtail_i18n/plugins/sites/forms.py
index ca582fd..40c7708 100644
--- a/wagtail_i18n/plugins/sites/forms.py
+++ b/wagtail_i18n/plugins/sites/forms.py
@@ -1,8 +1,10 @@
from django import forms
+from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from wagtail.admin.widgets import AdminPageChooser
+from wagtail_i18n.models import Region
from .models import Site, SiteLanguage
@@ -27,6 +29,10 @@ class SiteLanguageFormSet(SiteLanguageFormSetBase):
minimum_forms = 1
minimum_forms_message = _("Please specify at least one language for this site.")
+ @cached_property
+ def single_region(self):
+ return Region.objects.count() == 1
+
def add_fields(self, form, *args, **kwargs):
super().add_fields(form, *args, **kwargs)
@@ -35,3 +41,7 @@ class SiteLanguageFormSet(SiteLanguageFormSetBase):
# Use page chooser for root page
form.fields['root_page'].widget = AdminPageChooser()
+
+ # Hide region field if there is only one
+ if self.single_region:
+ form.fields['region'].widget = forms.HiddenInput()