Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Autocomplete fields for grouper selection and option for less verbose UI #433

Merged
merged 10 commits into from
Jan 15, 2025
11 changes: 9 additions & 2 deletions djangocms_versioning/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,9 @@ class VersionAdmin(ChangeListActionsMixin, admin.ModelAdmin, metaclass=MediaDefi
actions = ["compare_versions", "delete_selected"]
list_display = (
"number",
"created",
) + (
("created",) if conf.VERBOSE_UI else ()
) + (
"modified",
"content",
"created_by",
Expand All @@ -639,6 +641,9 @@ class VersionAdmin(ChangeListActionsMixin, admin.ModelAdmin, metaclass=MediaDefi
class Media:
js = ["djangocms_versioning/js/versioning.js"]

def has_module_permission(self, request):
return conf.VERBOSE_UI

def get_changelist(self, request, **kwargs):
return VersionChangeList

Expand Down Expand Up @@ -963,10 +968,12 @@ def grouper_form_view(self, request):
to show versions of.
"""
language = get_language_from_request(request)
versionable = versionables.for_content(self.model._source_model)
context = dict(
self.admin_site.each_context(request),
opts=self.model._meta,
form=grouper_form_factory(self.model._source_model, language)(),
form=grouper_form_factory(self.model._source_model, language, self.admin_site)(),
title=_("Select {} to view its versions").format(versionable.grouper_model._meta.verbose_name),
)
return render(request, "djangocms_versioning/admin/grouper_form.html", context)

Expand Down
6 changes: 6 additions & 0 deletions djangocms_versioning/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@
settings, "DJANGOCMS_VERISONING_ON_PUBLISH_REDIRECT", "published"
)
#: Allowed values: "versions", "published", "preview"

VERBOSE_UI = getattr(
settings, "DJANGOCMS_VERSIONING_VERBOSE_UI", True
)
#: If True, the version admin will be offered in the admin index
#: for each registered versionable model.
36 changes: 26 additions & 10 deletions djangocms_versioning/forms.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
from __future__ import annotations

from functools import lru_cache

from django import forms
from django.contrib.admin.widgets import AutocompleteSelect

from . import versionables


class VersionAutocompleteSelect(AutocompleteSelect):
def optgroups(self, name: str, value: str, attr: dict | None = None):
default = (None, [], 0)
default[1].append(self.create_option(name, "", "", False, 0))
return [default]

Check warning on line 15 in djangocms_versioning/forms.py

View check run for this annotation

Codecov / codecov/patch

djangocms_versioning/forms.py#L13-L15

Added lines #L13 - L15 were not covered by tests


class VersionContentChoiceField(forms.ModelChoiceField):
"""Form field used to display a list of grouper instances"""

def __init__(self, *args, **kwargs):
def __init__(self, *args, model=None, admin_site=None, **kwargs):
self.language = kwargs.pop("language")
self.predefined_label_method = kwargs.pop("option_label_override")
if getattr(admin_site._registry.get(model), "search_fields", []):
# If the model is registered in the admin, use the autocomplete widget
kwargs.setdefault("widget", VersionAutocompleteSelect(
model._meta.get_field(versionables.for_content(model).grouper_field_name),
admin_site=admin_site,
))
super().__init__(*args, **kwargs)

def label_from_instance(self, obj):
Expand All @@ -22,30 +38,30 @@


@lru_cache
def grouper_form_factory(content_model, language=None):
def grouper_form_factory(content_model, language=None, admin_site=None):
"""Returns a form class used for selecting a grouper to see versions of.
Form has a single field - grouper - which is a model choice field
with available grouper objects for specified content model.

:param content_model: Content model class
:param language: Language
"""
versionable = versionables.for_content(content_model)
valid_grouper_pk = content_model.admin_manager\
.latest_content()\
.values_list(versionable.grouper_field_name, flat=True)
if admin_site is None:
from django.contrib.admin import site
admin_site = site

versionable = versionables.for_content(content_model)
return type(
content_model.__name__ + "GrouperForm",
(forms.Form,),
{
"_content_model": content_model,
versionable.grouper_field_name: VersionContentChoiceField(
queryset=versionable.grouper_model.objects.filter(
pk__in=valid_grouper_pk,
),
label=versionable.grouper_model._meta.verbose_name,
label=versionable.grouper_model._meta.verbose_name.capitalize(),
queryset=versionable.grouper_model.objects.all(),
option_label_override=versionable.grouper_selector_option_label,
admin_site=admin_site,
model=content_model,
language=language,
),
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% extends "admin/base_site.html" %}
{% extends "admin/change_form.html" %}
{% load i18n admin_urls static admin_list %}

{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %}
Expand All @@ -13,6 +13,7 @@
{% endblock %}
{% endif %}

{% block extrastyle %}{{ block.super }}{{ form.media }}{% endblock extrastyle %}
{% block coltype %}flex{% endblock %}

{% block content %}
Expand All @@ -33,7 +34,13 @@
{% endblock %}
<div class="module" id="changelist">
<form action="{% url opts|admin_urlname:"changelist" %}">
{{ form }}
<fieldset class="module aligned">
<div class="form-row">
<div class="flex-container">
{{ form }}
</div>
</div>
</fieldset>
<button type="submit">{% translate "Submit" %}</button>
</form>
</form>
Expand Down
7 changes: 6 additions & 1 deletion docs/api/advanced_configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,12 @@ Must be defined if the :ref:`extra_grouping_fields` option has been set. This wi
grouper_selector_option_label
++++++++++++++++++++++++++++++

If the version table link is specified without a grouper param, a form with a dropdown of grouper objects will display. This setting defines how the labels of those groupers will display on the dropdown.
If the version table link is specified without a grouper param, a form with a dropdown of grouper objects will display. By default, if the grouper object is registered with the
admin and has a ``search_fields`` attribute, the dropdown will be an autocomplete
field which will display the object's ``__str__`` method. This is the recommended
method.

For models not registerd with the admin, or without search fields, this setting defines how the labels of those groupers will display on the dropdown (regular select field).


.. code-block:: python
Expand Down
10 changes: 10 additions & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,13 @@ Settings for djangocms Versioning
* ``"preview"``: The user will be redirected to the content object's
preview endpoint.

.. py:attribute:: DJANGOCMS_VERISONING_VERBOSE_UI

Defaults to ``True``

For many users it is sufficient to interact with djangocms-versioning
through a less verbose UI. If set to ``False``, djangocms-versioning will
not display the creation date in the "manage versions" view. Also, it will
remove its entries in the django admin overview page (index).
"manage versions" remains accessible trough the version menu in the CMS
toolbar.
Loading