Skip to content

Commit 461595c

Browse files
add confirmation page
1 parent a21833f commit 461595c

File tree

4 files changed

+139
-12
lines changed

4 files changed

+139
-12
lines changed

src/django_github_app/admin.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
from __future__ import annotations
22

3+
import datetime
4+
35
from django import forms
46
from django.contrib import admin
57
from django.contrib import messages
68
from django.http import HttpResponseRedirect
79
from django.shortcuts import render
810
from django.urls import path
911
from django.urls import reverse
12+
from django.utils import timezone
1013

1114
from .conf import app_settings
1215
from .models import EventLog
@@ -40,17 +43,49 @@ def get_urls(self):
4043
return custom_urls + urls
4144

4245
def cleanup_view(self, request):
46+
# handle confirmation
47+
if request.POST.get("post") == "yes":
48+
days_to_keep = int(request.POST.get("days_to_keep", 0))
49+
deleted_count, _ = EventLog.objects.cleanup_events(days_to_keep)
50+
event_text = "event" if deleted_count == 1 else "events"
51+
day_text = "day" if days_to_keep == 1 else "days"
52+
messages.success(
53+
request,
54+
f"Successfully deleted {deleted_count} {event_text} older than {days_to_keep} {day_text}.",
55+
)
56+
return HttpResponseRedirect(
57+
reverse("admin:django_github_app_eventlog_changelist")
58+
)
59+
60+
# show form or confirmation
4361
if request.method == "POST":
4462
form = EventLogCleanupForm(request.POST)
4563
if form.is_valid():
4664
days_to_keep = form.cleaned_data["days_to_keep"]
47-
deleted_count, _ = EventLog.objects.cleanup_events(days_to_keep)
48-
messages.success(
65+
cutoff_date = timezone.now() - datetime.timedelta(days=days_to_keep)
66+
events_to_delete = EventLog.objects.filter(received_at__lte=cutoff_date)
67+
delete_count = events_to_delete.count()
68+
69+
context = {
70+
**self.admin_site.each_context(request),
71+
"title": "Confirm Event Cleanup",
72+
"days_to_keep": days_to_keep,
73+
"delete_count": delete_count,
74+
"cutoff_date": cutoff_date,
75+
"opts": self.model._meta,
76+
"object_name": self.model._meta.verbose_name,
77+
"model_count": [
78+
(self.model._meta.verbose_name_plural, delete_count)
79+
]
80+
if delete_count
81+
else [],
82+
"perms_lacking": None,
83+
"protected": None,
84+
}
85+
return render(
4986
request,
50-
f"Successfully deleted {deleted_count} event(s) older than {days_to_keep} days.",
51-
)
52-
return HttpResponseRedirect(
53-
reverse("admin:django_github_app_eventlog_changelist")
87+
"admin/django_github_app/eventlog/cleanup_confirmation.html",
88+
context,
5489
)
5590
else:
5691
form = EventLogCleanupForm()

src/django_github_app/templates/admin/django_github_app/eventlog/cleanup.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<div class="submit-row">
2020
<input type="submit"
2121
value="{% translate 'Delete Events' %}"
22-
class="default"
22+
class="deletelink"
2323
name="_save">
2424
{% url opts|admin_urlname:'changelist' as changelist_url %}
2525
<a role="button"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{% extends "admin/delete_confirmation.html" %}
2+
{% load i18n admin_urls %}
3+
4+
{% block breadcrumbs %}
5+
<div class="breadcrumbs">
6+
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
7+
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
8+
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
9+
&rsaquo; {% translate 'Clean up Events' %}
10+
</div>
11+
{% endblock %}
12+
13+
{% block delete_confirm %}
14+
<p>{% blocktranslate count counter=delete_count %}You are about to delete {{ counter }} event older than {{ days_to_keep }} days.{% plural %}You are about to delete {{ counter }} events older than {{ days_to_keep }} days.{% endblocktranslate %}</p>
15+
16+
<p>{% blocktranslate %}All events received before {{ cutoff_date }} will be permanently deleted.{% endblocktranslate %}</p>
17+
18+
{% if model_count %}
19+
{% include "admin/includes/object_delete_summary.html" %}
20+
{% endif %}
21+
22+
<form method="post">{% csrf_token %}
23+
<div>
24+
<input type="hidden" name="post" value="yes">
25+
<input type="hidden" name="days_to_keep" value="{{ days_to_keep }}">
26+
<input type="submit" value="{% translate "Yes, I'm sure" %}">
27+
<a href="#" class="button cancel-link">{% translate "No, take me back" %}</a>
28+
</div>
29+
</form>
30+
{% endblock %}

tests/test_admin.py

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,30 @@ def test_cleanup_view_get(self, factory, admin_user, eventlog_admin):
6060
assert b"Clean up Events" in response.content
6161
assert b"Days to keep events" in response.content
6262

63+
def test_cleanup_view_post_shows_confirmation(self, client, admin_user, baker):
64+
# Create some test events
65+
now = timezone.now()
66+
baker.make(EventLog, _quantity=3, received_at=now - datetime.timedelta(days=10))
67+
baker.make(EventLog, _quantity=2, received_at=now - datetime.timedelta(days=2))
68+
69+
client.login(username="admin", password="adminpass")
70+
response = client.post(
71+
reverse("admin:django_github_app_eventlog_cleanup"),
72+
{"days_to_keep": "5"},
73+
)
74+
75+
assert response.status_code == 200
76+
assert b"You are about to delete 3 events" in response.content
77+
assert b"Yes, I" in response.content and b"m sure" in response.content
78+
6379
@patch("django_github_app.models.EventLog.objects.cleanup_events")
64-
def test_cleanup_view_post(self, mock_cleanup, client, admin_user):
80+
def test_cleanup_view_confirm_deletion(self, mock_cleanup, client, admin_user):
6581
mock_cleanup.return_value = (5, {"django_github_app.EventLog": 5})
6682

6783
client.login(username="admin", password="adminpass")
6884
response = client.post(
6985
reverse("admin:django_github_app_eventlog_cleanup"),
70-
{"days_to_keep": "3"},
86+
{"post": "yes", "days_to_keep": "3"},
7187
)
7288

7389
assert response.status_code == 302
@@ -77,7 +93,45 @@ def test_cleanup_view_post(self, mock_cleanup, client, admin_user):
7793
# Check success message
7894
messages = list(get_messages(response.wsgi_request))
7995
assert len(messages) == 1
80-
assert "Successfully deleted 5 event(s)" in str(messages[0])
96+
assert "Successfully deleted 5 events older than 3 days" in str(messages[0])
97+
98+
@patch("django_github_app.models.EventLog.objects.cleanup_events")
99+
def test_cleanup_view_confirm_deletion_singular_day(
100+
self, mock_cleanup, client, admin_user
101+
):
102+
mock_cleanup.return_value = (2, {"django_github_app.EventLog": 2})
103+
104+
client.login(username="admin", password="adminpass")
105+
response = client.post(
106+
reverse("admin:django_github_app_eventlog_cleanup"),
107+
{"post": "yes", "days_to_keep": "1"},
108+
)
109+
110+
assert response.status_code == 302
111+
112+
# Check success message uses singular "day" and plural "events"
113+
messages = list(get_messages(response.wsgi_request))
114+
assert len(messages) == 1
115+
assert "Successfully deleted 2 events older than 1 day" in str(messages[0])
116+
117+
@patch("django_github_app.models.EventLog.objects.cleanup_events")
118+
def test_cleanup_view_confirm_deletion_zero_events(
119+
self, mock_cleanup, client, admin_user
120+
):
121+
mock_cleanup.return_value = (0, {})
122+
123+
client.login(username="admin", password="adminpass")
124+
response = client.post(
125+
reverse("admin:django_github_app_eventlog_cleanup"),
126+
{"post": "yes", "days_to_keep": "7"},
127+
)
128+
129+
assert response.status_code == 302
130+
131+
# Check success message uses plural "events" for zero
132+
messages = list(get_messages(response.wsgi_request))
133+
assert len(messages) == 1
134+
assert "Successfully deleted 0 events older than 7 days" in str(messages[0])
81135

82136
def test_cleanup_view_integration(self, client, admin_user, baker):
83137
now = timezone.now()
@@ -102,11 +156,19 @@ def test_cleanup_view_integration(self, client, admin_user, baker):
102156
response = client.get(reverse("admin:django_github_app_eventlog_cleanup"))
103157
assert response.status_code == 200
104158

105-
# Test POST request
159+
# Test POST request - Step 1: Show confirmation
106160
response = client.post(
107161
reverse("admin:django_github_app_eventlog_cleanup"),
108162
{"days_to_keep": "5"},
109163
)
164+
assert response.status_code == 200
165+
assert b"You are about to delete 1 event" in response.content
166+
167+
# Test POST request - Step 2: Confirm deletion
168+
response = client.post(
169+
reverse("admin:django_github_app_eventlog_cleanup"),
170+
{"post": "yes", "days_to_keep": "5"},
171+
)
110172
assert response.status_code == 302
111173

112174
# Check that old event was deleted and recent event remains
@@ -116,4 +178,4 @@ def test_cleanup_view_integration(self, client, admin_user, baker):
116178
# Check success message
117179
messages = list(get_messages(response.wsgi_request))
118180
assert len(messages) == 1
119-
assert "Successfully deleted 1 event(s)" in str(messages[0])
181+
assert "Successfully deleted 1 event older than 5 days" in str(messages[0])

0 commit comments

Comments
 (0)