Skip to content

Commit

Permalink
fix: Add versioning actions to change forms
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun committed May 5, 2024
1 parent adce880 commit ee69dfb
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 22 deletions.
29 changes: 25 additions & 4 deletions djangocms_versioning/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from cms.models import PageContent
from cms.utils import get_language_from_request
from cms.utils.conf import get_cms_setting
from cms.utils.helpers import is_editable_model
from cms.utils.urlutils import add_url_parameters, static_with_version
from django.conf import settings
from django.contrib import admin, messages
Expand Down Expand Up @@ -822,6 +823,24 @@ def _get_unlock_link(self, obj, request):
disabled=not obj.check_unlock.as_bool(request.user),
)

def _get_settings_link(self, obj, request):
"""
Generate a settings button for the Versioning Admin
"""

# If the content object is not registered for frontend editing no action should be present
if is_editable_model(obj.__class__):
return ""

content_model = obj.versionable.content_model
settings_url = reverse(f"admin:{content_model._meta.app_label}_{content_model._meta.model_name}_change", args=(obj.content.pk,))

Check failure on line 836 in djangocms_versioning/admin.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

djangocms_versioning/admin.py:836:121: E501 Line too long (136 > 120)
return self.admin_action_button(
settings_url,
icon="settings",
title=_("Settings"),
name="settings",
)

def get_actions_list(self):
"""Returns all action links as a list"""
return self.get_state_actions()
Expand All @@ -848,6 +867,7 @@ def get_state_actions(self):
self._get_revert_link,
self._get_discard_link,
self._get_unlock_link,
self._get_settings_link,
]

@admin.action(
Expand Down Expand Up @@ -945,19 +965,20 @@ def publish_view(self, request, object_id):
request, self.model._meta, object_id
)

requested_redirect = request.GET.get("next", None)
if conf.ON_PUBLISH_REDIRECT in ("preview", "published"):
redirect_url=get_preview_url(version.content)
else:
redirect_url=version_list_url(version.content)

if not version.can_be_published():
self.message_user(request, _("Version cannot be published"), messages.ERROR)
return redirect(redirect_url)
return redirect(requested_redirect or redirect_url)
try:
version.check_publish(request.user)
except ConditionFailed as e:
self.message_user(request, force_str(e), messages.ERROR)
return redirect(redirect_url)
return redirect(requested_redirect or redirect_url)

# Publish the version
version.publish(request.user)
Expand All @@ -970,7 +991,7 @@ def publish_view(self, request, object_id):
if hasattr(version.content, "get_absolute_url"):
redirect_url = version.content.get_absolute_url() or redirect_url

return redirect(redirect_url)
return redirect(requested_redirect or redirect_url)

def unpublish_view(self, request, object_id):
"""Unpublishes the specified version and redirects back to the
Expand Down Expand Up @@ -1085,7 +1106,7 @@ def edit_redirect_view(self, request, object_id):
return redirect(version_list_url(version.content))

# Redirect
return redirect(get_editable_url(target.content))
return redirect(get_editable_url(target.content, request.GET.get("force_admin")))

def revert_view(self, request, object_id):
"""Reverts to the specified version i.e. creates a draft from it."""
Expand Down
11 changes: 2 additions & 9 deletions djangocms_versioning/cms_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ def on_page_content_archive(version):


class VersioningCMSPageAdminMixin(VersioningAdminMixin):
change_form_template = "admin/djangocms_versioning/page/change_form.html"

def get_readonly_fields(self, request, obj=None):
fields = super().get_readonly_fields(request, obj)
if obj:
Expand All @@ -281,15 +283,6 @@ def get_readonly_fields(self, request, obj=None):
fields.remove(f_name)
return fields

def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
if obj:
version = Version.objects.get_for_content(obj)
if not version.check_modify.as_bool(request.user):
for f_name in ["slug", "overwrite_url"]:
form.declared_fields[f_name].widget.attrs["readonly"] = True
return form

def get_queryset(self, request):
urls = ("cms_pagecontent_get_tree",)
queryset = super().get_queryset(request)
Expand Down
6 changes: 3 additions & 3 deletions djangocms_versioning/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,11 @@ def is_content_editable(placeholder, user):
return version.state == DRAFT


def get_editable_url(content_obj):
def get_editable_url(content_obj, force_admin=False):
"""If the object is editable the cms editable view should be used, with the toolbar.
This method is provides the URL for it.
This method provides the URL for it.
"""
if is_editable_model(content_obj.__class__):
if is_editable_model(content_obj.__class__) and not force_admin:
language = getattr(content_obj, "language", None)
url = get_object_edit_url(content_obj, language)
# Or else, the standard edit view should be used
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.object-tools a.accent {
background-color: var(--accent) !important;
}
.object-tools a.accent:hover,
.object-tools a.accent:active,
.object-tools a.accent:hover:active {
background-color: color-mix(in srgb, var(--accent) 90%, var(--dca-black)) !important;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
(function($) {
$(document).ready(function() {
$('.cms-form-post-method').on('click', function(e) {
e.preventDefault();
var csrf_token = document.querySelector('form input[name="csrfmiddlewaretoken"]').value;
var url = this.href;
var $form = $('<form method="post" action="' + url + '"></form>');
var $csrf = $(`<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}">`);
$form.append($csrf);
$form.appendTo('body').submit();
});
});
})(django.jQuery);
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{% extends "admin/cms/page/change_form.html" %}
{% load static admin_urls admin_modify djangocms_versioning i18n cms_admin %}

{% block extrahead %}
{{ block.super }}
<script src="{% static "djangocms_versioning/js/object-tools.js" %}"></script>
{% endblock %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="{% static "djangocms_versioning/css/object-tools.css" %}">
{% endblock %}

{% block content_title %}
{% if title %}<h1>{{ title }}{% if original %} - {{ original.versions.first.short_name }}{% endif %}</h1>{% endif %}
{% block object-tools %}
{% if not popup and not add %}
<ul class="object-tools hide-in-modal">
{% block object-tools-items %}
{% include "admin/djangocms_versioning/versioning_buttons.html" %}
<li>
{% get_preview_url original as admin_url %}
<a href="{{ admin_url }}" target="_parent">{% trans "Preview" %}</a>
</li>
{% endblock %}
</ul>
{% endif %}
{% endblock %}
{% endblock %}

{% block content %}
<div id="content-main">



<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="?language={{ language }}{%if request.GET.parent_node %}&amp;parent_node={{ request.GET.parent_node }}{% endif %}{%if request.GET.source %}&amp;source={{ request.GET.source }}{% endif %}" method="post" id="{{ opts.model_name }}_form">
{% csrf_token %}
{% block form_top %}{% endblock %}

{% if show_language_tabs and not show_permissions %}
<div id="page_form_lang_tabs">
{% for lang_code, lang_name in language_tabs %}
<input type="button" onclick="CMS.API.changeLanguage('{% get_admin_url_for_language cms_page lang_code %}');"
class="language_button {% if lang_code == language %}selected{% else %}{% if not lang_code in filled_languages %} notfilled{% endif %}{% endif %}"
id="{{lang_code}}button" name="{{lang_code}}" value="{{lang_name}}" />
{% endfor %}
<div class="lang_tabs_line"></div>
</div>
{% endif %}

<div id="lang_tab_content">
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
{% if save_on_top %}{% submit_row %}{% endif %}
{% if errors %}
<p class="errornote">
{% blocktrans count errors|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
</p>
<ul class="errorlist">{% for error in adminform.form.non_field_errors %}<li>{{ error }}</li>{% endfor %}</ul>
{% endif %}

{% for fieldset in adminform %}
{% include "admin/cms/page/includes/fieldset.html" %}
{% endfor %}

{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}

{% if show_permissions %}
<div class="inline-group">
<div class="tabular inline-related">
<fieldset id="inherited_permissions" class="module aligned collapse">
<h2>{% trans 'All permissions' %}</h2>
<div class="loading" rel="../permissions/">{% trans 'Loading...' %}</div>
</fieldset>
</div>
</div>
{% endif %}

{% block after_related_objects %}{% endblock %}

{% if add %}
<div class="submit-row"{% if is_popup %} style="overflow: auto;"{% endif %}>
<input type="submit" name="_save" class="default" value="{% trans 'Save' %}" {{ onclick_attrib }}/>
<input type="submit" name="_continue" value="{% trans 'Save and continue editing' %}" {{ onclick_attrib }}/>
</div>
{% else %}
{% page_submit_row %}
{% endif %}
</div>
</form>
</div>

{% block admin_change_form_document_ready %}
{{ block.super }}
{% endblock %}

{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}

{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% load djangocms_versioning i18n %}
{% with url=original|url_publish_version:request.user %}
{% if url %}
<li>
<a class="accent cms-form-post-method" href="{{ url }}?next={{ request.path }}">{% trans "Publish" %}</a>
</li>
{% endif %}
{% endwith %}
{% with url=original|url_new_draft:request.user %}
{% if url %}
<li>
<a class="accent cms-form-post-method" href="{{ url }}?force_admin=1">{% trans "New Draft" %}</a>
</li>
{% endif %}
{% endwith %}
{% with url=original|url_revert_version:request.user %}
{% if url %}
<li>
<a href="{{ url }}?next={{ request.path }}">{% trans "Revert" %}</a>
</li>
{% endif %}
{% endwith %}

{% with url=original|url_version_list %}
{% if url %}
<li>
<a href="{{ url }}">{% trans "Versions" %}</a>
</li>
{% endif %}
{% endwith %}
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{% extends versioning_fallback_change_form_template|default:"admin/change_form.html" %}
{% load i18n admin_urls djangocms_versioning %}
{% load static %}

{% block extrahead %}
{{ block.super }}
<script src="{% static "djangocms_versioning/js/object-tools.js" %}"></script>
{% endblock %}

{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="{% static "djangocms_versioning/css/object-tools.css" %}">
{% endblock %}

{% block object-tools-items %}
<li>
<a href="{{ original|url_version_list }}">
{% translate "Versions" %}
</a>
</li>
{% include "admin/djangocms_versioning/versioning_buttons.html" %}
{{ block.super }}
{% endblock %}

38 changes: 38 additions & 0 deletions djangocms_versioning/templatetags/djangocms_versioning.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django import template
from django.urls import reverse

from .. import versionables, constants
from ..helpers import version_list_url

register = template.Library()

Check failure on line 7 in djangocms_versioning/templatetags/djangocms_versioning.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

djangocms_versioning/templatetags/djangocms_versioning.py:1:1: I001 Import block is un-sorted or un-formatted
Expand All @@ -8,3 +10,39 @@
@register.filter
def url_version_list(content):
return version_list_url(content)

@register.filter
def url_publish_version(content, user):
version = content.versions.first()
if version:
if version.check_publish.as_bool(user):
proxy_model = versionables.for_content(content).version_model_proxy
return reverse(
f"admin:{proxy_model._meta.app_label}_{proxy_model.__name__.lower()}_publish",
args=(version.pk,),
)
return ""

@register.filter
def url_new_draft(content, user):
version = content.versions.first()
if version:
if version.state == constants.PUBLISHED:
proxy_model = versionables.for_content(content).version_model_proxy
return reverse(
f"admin:{proxy_model._meta.app_label}_{proxy_model.__name__.lower()}_edit_redirect",
args=(version.pk,),
)
return ""

@register.filter
def url_revert_version(content, user):
version = content.versions.first()
if version:
if version.check_revert.as_bool(user):
proxy_model = versionables.for_content(content).version_model_proxy
return reverse(
f"admin:{proxy_model._meta.app_label}_{proxy_model.__name__.lower()}_revert",
args=(version.pk,),
)
return ""

0 comments on commit ee69dfb

Please sign in to comment.