8000 feat: Improved delete page confirmation message (#8070) · django-cms/django-cms@47b6301 · GitHub
[go: up one dir, main page]

Skip to content

Commit 47b6301

Browse files
fsbraunGithub Release Action
andauthored
feat: Improved delete page confirmation message (#8070)
* first stab at delete confirmation message * Update delete confirmation * Prepare data in admin * Fix flake8 issues * Fix py3.9 type annotation --------- Co-authored-by: Github Release Action <info@django-cms.org>
1 parent c7208ed commit 47b6301

File tree

5 files changed

+128
-5
lines changed

5 files changed

+128
-5
lines changed

cms/admin/pageadmin.py

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import json
24
import re
35
from collections import namedtuple
@@ -34,6 +36,8 @@
3436
from django.urls import re_path
3537
from django.utils.decorators import method_decorator
3638
from django.utils.encoding import force_str
39+
from django.utils.safestring import mark_safe
40+
from django.utils.text import capfirst
3741
from django.utils.translation import gettext as _
3842
from django.views.decorators.http import require_POST
3943

@@ -350,10 +354,45 @@ def response_delete(self, request, obj_display, obj_id):
350354
return super().response_delete(request, obj_display, obj_id)
351355

352356
def get_deleted_objects(self, objs, request):
353-
deleted_objs = list(objs)
354-
for obj in objs:
355-
deleted_objs.extend(obj.get_descendant_pages())
356-
return super().get_deleted_objects(deleted_objs, request)
357+
"""Minimize complexity of delete selected confirmation: Only show pages, page contents and plugins numbers,
358+
only show Page and PageContent objects in the details.
359+
"""
360+
def recursively_remove(deleted_objects: list | str) -> list:
361+
"""Remove all objects that are not Page or PageContent from the nested list of deleted objects.
362+
Reformat the messages."""
363+
if isinstance(deleted_objects, str):
364+
return deleted_objects
365+
result = []
366+
for obj in deleted_objects:
367+
item = recursively_remove(obj)
368 8000 +
if isinstance(item, str):
369+
if obj.startswith(f"{capfirst(Page._meta.verbose_name)}: "):
370+
text = re.findall(r'>(.*)<', obj)
371+
if text:
372+
result.append(mark_safe("<b>" + text[0] + "</b>"))
373+
else:
374+
result.append(mark_safe(
375+
"<b>" + item.removeprefix(f"{capfirst(Page._meta.verbose_name)}: ") + "</b>"
376+
))
377+
elif obj.startswith(f"{capfirst(PageContent._meta.verbose_name)}: "):
378+
result.insert(0, mark_safe(
379+
item.removeprefix(f"{capfirst(PageContent._meta.verbose_name)}: ")
380+
))
381+
elif item:
382+
result.append(item)
383+
return result
384+
385+
to_delete, model_count, perms_needed, protected = super().get_deleted_objects(objs, request)
386+
to_delete = recursively_remove(to_delete)
387+
model_count = {
388+
key: value for key, value in model_count.items() if key in (
389+
Page._meta.verbose_name_plural,
390+
PageContent._meta.verbose_name_plural,
391+
CMSPlugin._meta.verbose_name_plural
392+
)
393+
}
394+
395+
return to_delete, model_count, perms_needed, protected
357396

358397
def delete_model(self, request, obj):
359398
operation_token = send_pre_page_operation(

cms/migrations/0025_remove_plugin_tree_fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Migration(migrations.Migration):
1313
operations = [
1414
migrations.AlterModelOptions(
1515
name='cmsplugin',
16-
options={'ordering': ('position',)},
16+
options={'ordering': ('position',), 'verbose_name': 'plugin', 'verbose_name_plural': 'plugins'},
1717
),
1818
migrations.AlterField(
1919
model_name='cmsplugin',

cms/models/pluginmodel.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ class CMSPlugin(models.Model, metaclass=PluginModelBase):
170170
child_plugin_instances = None
171171

172172
class Meta:
173+
verbose_name = _("plugin")
174+
verbose_name_plural = _("plugins")
173175
app_label = 'cms'
174176
ordering = ('position',)
175177
indexes = [
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{% extends "admin/delete_confirmation.html" %}
2+
{% load i18n admin_urls static cms_admin %}
3+
{% block extrahead %}{{ block.super }}
4+
<style>
5+
.flexbox {
6+
display: flex;
7+
justify-content: space-between;
8+
margin-bottom: 2em;
9+
margin-top: 2em;
10+
+ hr {
11+
margin: 3em 0;
12+
}
13+
}
14+
.summary .count {
15+
margin-inline-start: 0.5em;
16+
font-size: 300%;
17+
}
18+
ul#deleted-objects {
19+
padding: 0;
20+
li {
21+
list-style-type: none;
22+
background(var(--body-bg));
23+
&:has( > :not(a)) {
24+
border-top: 1px solid var(--border-color);
25+
}
26+
}
27+
ul {
28+
margin-inline-start: 0;
29+
padding-inline-start: 1em;
30+
}
31+
}
32+
form {
33+
padding: 1em 0;
34+
}
35+
</style>
36+
{% endblock %}
37+
{% block delete_confirm %}
38+
<p>
39+
{% blocktranslate with escaped_object=object %}Are you sure you want to delete the {{ object_name }} "{{ escaped_object }}"? All of the following related items will be deleted:{% endblocktranslate %}
40+
</p>
41+
42+
<div class="flexbox">
43+
{% for model, count in model_count %}
44+
<h2 class="summary">
45+
{{ model|capfirst }}<span class="count">{{ count }}</span>
46+
</h2>
47+
{% endfor %}
48+
</div>
49+
<h2>{% translate "Structure" %}</h2>
50+
<ul id="deleted-objects">{{ deleted_objects|unordered_list }}</ul>
51+
<hr>
52+
<form method="post">{% csrf_token %}
53+
<div>
54+
<input type="hidden" name="post" value="yes">
55+
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
56+
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
57+
<input type="submit" value="{% translate 'Yes, I’m sure' %}">
58+
<a href="#" class="button cancel-link">{% translate "No, take me back" %}</a>
59+
</div>
60+
</form>
61+
{% endblock %}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% load i18n %}
2+
<h2>{% translate "Summary" %}</h2>
3+
<div class="flexbox">
4+
{% for model, count in model_count %}
5+
<div class="summary">
6+
{{ model|capfirst }}: <span class="count">{{ count }}</span>
7+
</div>
8+
{% endfor %}
9+
<div class="summary page-contents">
10+
{{ summary.PageContent.0|capfirst }}: <span class="count">{{ summary.PageContent.1 }}</span>
11+
</div>
12+
<div class="summary plugins">
13+
{{ summary.CMSPlugin.0|capfirst }}: <span class="count">{{ summary.CMSPlugin.1 }}</span>
14+
</div>
15+
</div>
16+
<ul class="other">
17+
{% for name, number in model_count %}
18+
<li><span class="name">{{ name|capfirst }}:</span><span class="number">{{ number }}</span></li>
19+
{% endfor %}
20+
</ul>
21+

0 commit comments

Comments
 (0)
0