#6477 Customizable Group create/edit page

Open seifert
Coverage Reach
wagtail/admin/views/pages/edit.py wagtail/admin/views/pages/create.py wagtail/admin/views/pages/revisions.py wagtail/admin/views/pages/workflow.py wagtail/admin/views/pages/preview.py wagtail/admin/views/pages/search.py wagtail/admin/views/pages/history.py wagtail/admin/views/pages/moderation.py wagtail/admin/views/pages/move.py wagtail/admin/views/pages/copy.py wagtail/admin/views/pages/listing.py wagtail/admin/views/pages/lock.py wagtail/admin/views/pages/convert_alias.py wagtail/admin/views/pages/unpublish.py wagtail/admin/views/pages/delete.py wagtail/admin/views/pages/ordering.py wagtail/admin/views/pages/usage.py wagtail/admin/views/pages/utils.py wagtail/admin/views/workflows.py wagtail/admin/views/generic.py wagtail/admin/views/account.py wagtail/admin/views/mixins.py wagtail/admin/views/chooser.py wagtail/admin/views/reports.py wagtail/admin/views/collections.py wagtail/admin/views/home.py wagtail/admin/views/page_privacy.py wagtail/admin/views/collection_privacy.py wagtail/admin/views/userbar.py wagtail/admin/views/tags.py wagtail/admin/rich_text/converters/html_to_contentstate.py wagtail/admin/rich_text/converters/editor_html.py wagtail/admin/rich_text/converters/html_ruleset.py wagtail/admin/rich_text/converters/contentstate_models.py wagtail/admin/rich_text/converters/contentstate.py wagtail/admin/rich_text/editors/hallo.py wagtail/admin/rich_text/editors/draftail/__init__.py wagtail/admin/rich_text/editors/draftail/features.py wagtail/admin/rich_text/__init__.py wagtail/admin/edit_handlers.py wagtail/admin/forms/collections.py wagtail/admin/forms/workflows.py wagtail/admin/forms/pages.py wagtail/admin/forms/models.py wagtail/admin/forms/choosers.py wagtail/admin/forms/view_restrictions.py wagtail/admin/forms/tags.py wagtail/admin/forms/auth.py wagtail/admin/forms/search.py wagtail/admin/forms/__init__.py wagtail/admin/compare.py wagtail/admin/widgets/chooser.py wagtail/admin/widgets/datetime.py wagtail/admin/widgets/button.py wagtail/admin/widgets/filtered_select.py wagtail/admin/widgets/tags.py wagtail/admin/widgets/workflows.py wagtail/admin/widgets/button_select.py wagtail/admin/widgets/auto_height_text.py wagtail/admin/widgets/__init__.py wagtail/admin/wagtail_hooks.py wagtail/admin/templatetags/wagtailadmin_tags.py wagtail/admin/templatetags/wagtailuserbar.py wagtail/admin/static_src/wagtailadmin/js/page-editor.js wagtail/admin/static_src/wagtailadmin/js/vendor/urlify.js wagtail/admin/static_src/wagtailadmin/js/vendor/jquery-3.5.1.min.js wagtail/admin/static_src/wagtailadmin/app/wagtailadmin.entry.js wagtail/admin/static_src/wagtailadmin/app/draftail.entry.js wagtail/admin/action_menu.py wagtail/admin/mail.py wagtail/admin/api/serializers.py wagtail/admin/api/views.py wagtail/admin/api/filters.py wagtail/admin/api/urls.py wagtail/admin/filters.py wagtail/admin/auth.py wagtail/admin/menu.py wagtail/admin/userbar.py wagtail/admin/viewsets/model.py wagtail/admin/viewsets/__init__.py wagtail/admin/viewsets/base.py wagtail/admin/checks.py wagtail/admin/search.py wagtail/admin/urls/__init__.py wagtail/admin/urls/pages.py wagtail/admin/urls/collections.py wagtail/admin/urls/workflows.py wagtail/admin/urls/reports.py wagtail/admin/urls/password_reset.py wagtail/admin/site_summary.py wagtail/admin/messages.py wagtail/admin/log_action_registry.py wagtail/admin/staticfiles.py wagtail/admin/navigation.py wagtail/admin/models.py wagtail/admin/signal_handlers.py wagtail/admin/localization.py wagtail/admin/modal_workflow.py wagtail/admin/apps.py wagtail/admin/jinja2tags.py wagtail/admin/datetimepicker.py wagtail/admin/blocks.py wagtail/admin/signals.py wagtail/admin/__init__.py wagtail/contrib/modeladmin/views.py wagtail/contrib/modeladmin/options.py wagtail/contrib/modeladmin/helpers/button.py wagtail/contrib/modeladmin/helpers/permission.py wagtail/contrib/modeladmin/helpers/url.py wagtail/contrib/modeladmin/helpers/search.py wagtail/contrib/modeladmin/helpers/__init__.py wagtail/contrib/modeladmin/templatetags/modeladmin_tags.py wagtail/contrib/modeladmin/menus.py wagtail/contrib/modeladmin/mixins.py wagtail/contrib/modeladmin/forms.py wagtail/contrib/modeladmin/apps.py wagtail/contrib/modeladmin/__init__.py wagtail/contrib/redirects/views.py wagtail/contrib/redirects/base_formats.py wagtail/contrib/redirects/management/commands/import_redirects.py wagtail/contrib/redirects/models.py wagtail/contrib/redirects/forms.py wagtail/contrib/redirects/tmp_storages.py wagtail/contrib/redirects/middleware.py wagtail/contrib/redirects/utils.py wagtail/contrib/redirects/wagtail_hooks.py wagtail/contrib/redirects/apps.py wagtail/contrib/redirects/urls.py wagtail/contrib/redirects/permissions.py wagtail/contrib/redirects/__init__.py wagtail/contrib/postgres_search/backend.py wagtail/contrib/postgres_search/query.py wagtail/contrib/postgres_search/utils.py wagtail/contrib/postgres_search/models.py wagtail/contrib/postgres_search/apps.py wagtail/contrib/postgres_search/__init__.py wagtail/contrib/forms/views.py wagtail/contrib/forms/models.py wagtail/contrib/forms/forms.py wagtail/contrib/forms/utils.py wagtail/contrib/forms/edit_handlers.py wagtail/contrib/forms/wagtail_hooks.py wagtail/contrib/forms/apps.py wagtail/contrib/forms/urls.py wagtail/contrib/forms/__init__.py wagtail/contrib/frontend_cache/tests.py wagtail/contrib/frontend_cache/backends.py wagtail/contrib/frontend_cache/utils.py wagtail/contrib/frontend_cache/signal_handlers.py wagtail/contrib/frontend_cache/apps.py wagtail/contrib/frontend_cache/__init__.py wagtail/contrib/search_promotions/tests.py wagtail/contrib/search_promotions/views.py wagtail/contrib/search_promotions/forms.py wagtail/contrib/search_promotions/wagtail_hooks.py wagtail/contrib/search_promotions/models.py wagtail/contrib/search_promotions/templatetags/wagtailsearchpromotions_tags.py wagtail/contrib/search_promotions/apps.py wagtail/contrib/search_promotions/admin_urls.py wagtail/contrib/search_promotions/__init__.py wagtail/contrib/routable_page/tests.py wagtail/contrib/routable_page/models.py wagtail/contrib/routable_page/templatetags/wagtailroutablepage_tags.py wagtail/contrib/routable_page/apps.py wagtail/contrib/routable_page/__init__.py wagtail/contrib/settings/views.py wagtail/contrib/settings/models.py wagtail/contrib/settings/jinja2tags.py wagtail/contrib/settings/registry.py wagtail/contrib/settings/context_processors.py wagtail/contrib/settings/forms.py wagtail/contrib/settings/templatetags/wagtailsettings_tags.py wagtail/contrib/settings/wagtail_hooks.py wagtail/contrib/settings/apps.py wagtail/contrib/settings/urls.py wagtail/contrib/settings/permissions.py wagtail/contrib/settings/__init__.py wagtail/contrib/table_block/tests.py wagtail/contrib/table_block/blocks.py wagtail/contrib/table_block/templatetags/table_block_tags.py wagtail/contrib/table_block/apps.py wagtail/contrib/table_block/__init__.py wagtail/contrib/sitemaps/tests.py wagtail/contrib/sitemaps/sitemap_generator.py wagtail/contrib/sitemaps/views.py wagtail/contrib/sitemaps/apps.py wagtail/contrib/sitemaps/__init__.py wagtail/contrib/styleguide/views.py wagtail/contrib/styleguide/wagtail_hooks.py wagtail/contrib/styleguide/tests.py wagtail/contrib/styleguide/apps.py wagtail/contrib/styleguide/__init__.py wagtail/core/models.py wagtail/core/blocks/field_block.py wagtail/core/blocks/stream_block.py wagtail/core/blocks/base.py wagtail/core/blocks/struct_block.py wagtail/core/blocks/list_block.py wagtail/core/blocks/static_block.py wagtail/core/blocks/__init__.py wagtail/core/blocks/utils.py wagtail/core/management/commands/fixtree.py wagtail/core/management/commands/publish_scheduled_pages.py wagtail/core/management/commands/create_log_entries_from_revisions.py wagtail/core/management/commands/replace_text.py wagtail/core/management/commands/purge_revisions.py wagtail/core/management/commands/move_pages.py wagtail/core/management/commands/set_url_paths.py wagtail/core/permission_policies/collections.py wagtail/core/permission_policies/base.py wagtail/core/permission_policies/__init__.py wagtail/core/query.py wagtail/core/rich_text/rewriters.py wagtail/core/rich_text/feature_registry.py wagtail/core/rich_text/__init__.py wagtail/core/rich_text/pages.py wagtail/core/utils.py wagtail/core/templatetags/wagtailcore_tags.py wagtail/core/fields.py wagtail/core/whitelist.py wagtail/core/treebeard.py wagtail/core/wagtail_hooks.py wagtail/core/hooks.py wagtail/core/jinja2tags.py wagtail/core/views.py wagtail/core/signal_handlers.py wagtail/core/forms.py wagtail/core/workflows.py wagtail/core/sites.py wagtail/core/signals.py wagtail/core/urls.py wagtail/core/apps.py wagtail/core/url_routing.py wagtail/core/compat.py wagtail/core/permissions.py wagtail/core/__init__.py wagtail/core/exceptions.py wagtail/images/views/images.py wagtail/images/views/multiple.py wagtail/images/views/chooser.py wagtail/images/views/serve.py wagtail/images/models.py wagtail/images/image_operations.py wagtail/images/rect.py wagtail/images/templatetags/wagtailimages_tags.py wagtail/images/wagtail_hooks.py wagtail/images/fields.py wagtail/images/rich_text/contentstate.py wagtail/images/rich_text/editor_html.py wagtail/images/rich_text/__init__.py wagtail/images/formats.py wagtail/images/api/v2/views.py wagtail/images/api/v2/serializers.py wagtail/images/api/fields.py wagtail/images/api/admin/views.py wagtail/images/api/admin/serializers.py wagtail/images/utils.py wagtail/images/forms.py wagtail/images/checks.py wagtail/images/blocks.py wagtail/images/widgets.py wagtail/images/jinja2tags.py wagtail/images/signal_handlers.py wagtail/images/edit_handlers.py wagtail/images/__init__.py wagtail/images/apps.py wagtail/images/shortcuts.py wagtail/images/admin.py wagtail/images/admin_urls.py wagtail/images/permissions.py wagtail/images/urls.py wagtail/images/exceptions.py wagtail/search/backends/elasticsearch2.py wagtail/search/backends/base.py wagtail/search/backends/db.py wagtail/search/backends/elasticsearch7.py wagtail/search/backends/__init__.py wagtail/search/backends/elasticsearch5.py wagtail/search/backends/elasticsearch6.py wagtail/search/index.py wagtail/search/management/commands/update_index.py wagtail/search/management/commands/search_garbage_collect.py wagtail/search/management/commands/wagtail_update_index.py wagtail/search/utils.py wagtail/search/models.py wagtail/search/query.py wagtail/search/views/queries.py wagtail/search/signal_handlers.py wagtail/search/apps.py wagtail/search/queryset.py wagtail/search/wagtail_hooks.py wagtail/search/urls/admin.py wagtail/search/forms.py wagtail/search/__init__.py wagtail/users/tests.py wagtail/users/forms.py wagtail/users/views/users.py wagtail/users/views/groups.py wagtail/users/wagtail_hooks.py wagtail/users/templatetags/wagtailusers_tags.py wagtail/users/models.py wagtail/users/utils.py wagtail/users/apps.py wagtail/users/widgets.py wagtail/users/urls/users.py wagtail/users/__init__.py wagtail/snippets/tests.py wagtail/snippets/views/snippets.py wagtail/snippets/views/chooser.py wagtail/snippets/action_menu.py wagtail/snippets/wagtail_hooks.py wagtail/snippets/widgets.py wagtail/snippets/models.py wagtail/snippets/blocks.py wagtail/snippets/permissions.py wagtail/snippets/templatetags/wagtailsnippets_admin_tags.py wagtail/snippets/edit_handlers.py wagtail/snippets/apps.py wagtail/snippets/urls.py wagtail/snippets/__init__.py wagtail/api/v2/views.py wagtail/api/v2/serializers.py wagtail/api/v2/filters.py wagtail/api/v2/utils.py wagtail/api/v2/router.py wagtail/api/v2/signal_handlers.py wagtail/api/v2/pagination.py wagtail/api/v2/apps.py wagtail/api/v2/__init__.py wagtail/api/conf.py wagtail/api/__init__.py wagtail/documents/views/documents.py wagtail/documents/views/chooser.py wagtail/documents/views/serve.py wagtail/documents/views/multiple.py wagtail/documents/models.py wagtail/documents/wagtail_hooks.py wagtail/documents/rich_text/editor_html.py wagtail/documents/rich_text/contentstate.py wagtail/documents/rich_text/__init__.py wagtail/documents/api/v2/views.py wagtail/documents/api/v2/serializers.py wagtail/documents/api/admin/views.py wagtail/documents/forms.py wagtail/documents/widgets.py wagtail/documents/blocks.py wagtail/documents/__init__.py wagtail/documents/apps.py wagtail/documents/signal_handlers.py wagtail/documents/admin.py wagtail/documents/edit_handlers.py wagtail/documents/admin_urls.py wagtail/documents/permissions.py wagtail/documents/urls.py wagtail/embeds/finders/oembed.py wagtail/embeds/finders/embedly.py wagtail/embeds/finders/__init__.py wagtail/embeds/finders/base.py wagtail/embeds/oembed_providers.py wagtail/embeds/rich_text/contentstate.py wagtail/embeds/rich_text/__init__.py wagtail/embeds/rich_text/editor_html.py wagtail/embeds/blocks.py wagtail/embeds/models.py wagtail/embeds/views/chooser.py wagtail/embeds/embeds.py wagtail/embeds/wagtail_hooks.py wagtail/embeds/templatetags/wagtailembeds_tags.py wagtail/embeds/format.py wagtail/embeds/apps.py wagtail/embeds/exceptions.py wagtail/embeds/forms.py wagtail/embeds/urls.py wagtail/embeds/__init__.py wagtail/utils/sendfile.py wagtail/utils/setup.py wagtail/utils/sendfile_streaming_backend.py wagtail/utils/deprecation.py wagtail/utils/decorators.py wagtail/utils/version.py wagtail/utils/widgets.py wagtail/utils/apps.py wagtail/utils/loading.py wagtail/utils/urlpatterns.py wagtail/utils/utils.py wagtail/sites/tests.py wagtail/sites/views.py wagtail/sites/wagtail_hooks.py wagtail/sites/forms.py wagtail/sites/apps.py wagtail/sites/__init__.py wagtail/locales/tests.py wagtail/locales/views.py wagtail/locales/wagtail_hooks.py wagtail/locales/forms.py wagtail/locales/utils.py wagtail/locales/apps.py wagtail/locales/__init__.py wagtail/bin/wagtail.py wagtail/__init__.py client/src/components/Draftail/sources/ModalWorkflowSource.js client/src/components/Draftail/decorators/TooltipEntity.js client/src/components/Draftail/decorators/Link.js client/src/components/Draftail/decorators/Document.js client/src/components/Draftail/blocks/MediaBlock.js client/src/components/Draftail/blocks/ImageBlock.js client/src/components/Draftail/blocks/EmbedBlock.js client/src/components/Draftail/EditorFallback/EditorFallback.js client/src/components/Draftail/index.js client/src/components/Draftail/DraftUtils.js client/src/components/Draftail/Tooltip/Tooltip.js client/src/components/Explorer/ExplorerPanel.js client/src/components/Explorer/actions.js client/src/components/Explorer/reducers/nodes.js client/src/components/Explorer/reducers/explorer.js client/src/components/Explorer/Explorer.js client/src/components/Explorer/ExplorerItem.js client/src/components/Explorer/index.js client/src/components/Explorer/ExplorerHeader.js client/src/components/Explorer/ExplorerToggle.js client/src/components/Explorer/PageCount.js client/src/components/Portal/Portal.js client/src/components/Button/Button.js client/src/components/UpgradeNotification/index.js client/src/components/Transition/Transition.js client/src/components/Icon/Icon.js client/src/components/PublicationStatus/PublicationStatus.js client/src/components/LoadingSpinner/LoadingSpinner.js client/src/includes/initSubmenus.js client/src/includes/initSkipLink.js client/src/utils/focus.js client/src/utils/version.js client/src/utils/actions.js client/src/api/client.js client/src/api/admin.js client/src/config/wagtailConfig.js

Flags

Flags have been temporarily removed from this view while the flagging feature is refactored for better performance and user experience.

You can still use flags when viewing individual files. Flag-level thresholds will also remain on pull and merge requests in your repository provider.

More information can be found in our documentation.


@@ -1,6 +1,9 @@
Loading
1 +
from django.conf import settings
1 2
from django.contrib.auth.models import Permission
3 +
from django.core.exceptions import ImproperlyConfigured
2 4
from django.db.models import Q
3 5
from django.urls import include, path, reverse
6 +
from django.utils.module_loading import import_string
4 7
from django.utils.translation import gettext_lazy as _
5 8
6 9
from wagtail.admin.menu import MenuItem
@@ -20,9 +23,25 @@
Loading
20 23
    ]
21 24
22 25
26 +
def get_group_view_set_cls():
27 +
    viewset_setting = 'WAGTAIL_GROUP_VIEW_SET'
28 +
    if hasattr(settings, viewset_setting):
29 +
        try:
30 +
            group_view_set_cls = import_string(getattr(settings, viewset_setting))
31 +
        except ImportError:
32 +
            raise ImproperlyConfigured(
33 +
                "%s refers to a class '%s' that is not available" %
34 +
                (viewset_setting, getattr(settings, viewset_setting))
35 +
            )
36 +
    else:
37 +
        group_view_set_cls = GroupViewSet
38 +
    return group_view_set_cls
39 +
40 +
23 41
@hooks.register('register_admin_viewset')
24 42
def register_viewset():
25 -
    return GroupViewSet('wagtailusers_groups', url_prefix='groups')
43 +
    group_view_set_cls = get_group_view_set_cls()
44 +
    return group_view_set_cls('wagtailusers_groups', url_prefix='groups')
26 45
27 46
28 47
# Typically we would check the permission 'auth.change_user' (and 'auth.add_user' /

@@ -16,7 +16,9 @@
Loading
16 16
from wagtail.tests.utils import WagtailTestUtils
17 17
from wagtail.users.forms import UserCreationForm, UserEditForm
18 18
from wagtail.users.models import UserProfile
19 +
from wagtail.users.views.groups import GroupViewSet
19 20
from wagtail.users.views.users import get_user_creation_form, get_user_edit_form
21 +
from wagtail.users.wagtail_hooks import get_group_view_set_cls
20 22
21 23
22 24
delete_user_perm_codename = "delete_{0}".format(AUTH_USER_MODEL_NAME.lower())
@@ -37,6 +39,10 @@
Loading
37 39
    attachment = forms.FileField(required=True, label="Attachment")
38 40
39 41
42 +
class CustomGroupViewSet(GroupViewSet):
43 +
    icon = 'custom-icon'
44 +
45 +
40 46
class TestUserFormHelpers(TestCase):
41 47
42 48
    def test_get_user_edit_form_with_default_form(self):
@@ -1576,3 +1582,22 @@
Loading
1576 1582
        # See that the non-registered permission is still there
1577 1583
        self.assertEqual(self.test_group.permissions.count(), 1)
1578 1584
        self.assertEqual(self.test_group.permissions.all()[0], self.non_registered_perm)
1585 +
1586 +
1587 +
class TestGroupViewSet(TestCase):
1588 +
    def test_get_group_view_set(self):
1589 +
        self.assertIs(get_group_view_set_cls(), GroupViewSet)
1590 +
1591 +
    @override_settings(
1592 +
        WAGTAIL_GROUP_VIEW_SET='wagtail.users.tests.CustomGroupViewSet'
1593 +
    )
1594 +
    def test_get_group_view_set_with_custom_form(self):
1595 +
        group_view_set = get_group_view_set_cls()
1596 +
        self.assertIs(group_view_set, CustomGroupViewSet)
1597 +
        self.assertEqual(group_view_set.icon, 'custom-icon')
1598 +
1599 +
    @override_settings(
1600 +
        WAGTAIL_GROUP_VIEW_SET='wagtail.users.tests.CustomGroupViewSetNotExist'
1601 +
    )
1602 +
    def test_get_group_view_set_with_custom_form_not_exist(self):
1603 +
        self.assertRaises(ImproperlyConfigured, get_group_view_set_cls)

Everything is accounted for!

No changes detected that need to be reviewed.
What changes does Codecov check for?
Lines, not adjusted in diff, that have changed coverage data.
Files that introduced coverage data that had none before.
Files that have missing coverage data that once were tracked.
Files Coverage
client/src 92.85%
wagtail 0.01% 90.02%
Project Totals (436 files) 90.11%
Loading