Skip to content
Snippets Groups Projects
Unverified Commit f9de1f19 authored by Brian Mesick's avatar Brian Mesick Committed by GitHub
Browse files

Merge pull request #18911 from edx/bmedx/add_unretire_button

Add admin UI to cancel pending retirements
parents 3c04f41d 405a8ada
No related merge requests found
{% extends "admin/change_form.html" %}
{% load i18n admin_static admin_modify %}
{% block content %}
<div id="content-main">
<form action="" method="POST">
{% csrf_token %}
{% if form.non_field_errors|length > 0 %}
<p class="errornote">
{% trans "Please correct the errors below." %}
</p>
{{ form.non_field_errors }}
{% endif %}
{% blocktrans with username=retirement.user.username %}Are you sure you want to cancel retirement for user "{{ username }}"? {% endblocktrans %}
<fieldset class="module aligned">
{% for field in form %}
<div class="form-row">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
{% if field.field.help_text %}
<p class="help">
{{ field.field.help_text|safe }}
</p>
{% endif %}
</div>
{% endfor %}
</fieldset>
<div class="submit-row">
<input type="submit" class="default" value="{% trans 'Submit' %}">
</div>
</form>
</div>
{% endblock %}
"""
Django forms for accounts
"""
from django import forms
from django.core.exceptions import ValidationError
class RetirementQueueDeletionForm(forms.Form):
"""
Admin form to facilitate learner retirement cancellation
"""
cancel_retirement = forms.BooleanField(required=True)
def save(self, retirement):
"""
When the form is POSTed we double-check the retirment status
and perform the necessary steps to cancel the retirement
request.
"""
if retirement.current_state.state_name != 'PENDING':
self.add_error(
None,
# Translators: 'current_state' is a string from an enumerated list indicating the learner's retirement
# state. Example: FORUMS_COMPLETE
"Retirement requests can only be cancelled for users in the PENDING state."
" Current request state for '{original_username}': {current_state}".format(
original_username=retirement.original_username,
current_state=retirement.current_state.state_name
)
)
raise ValidationError('Retirement is in the wrong state!')
# Load the user record using the retired email address -and- change the email address back.
retirement.user.email = retirement.original_email
retirement.user.save()
# Delete the user retirement status record.
# No need to delete the accompanying "permanent" retirement request record - it gets done via Django signal.
retirement.delete()
"""
Django admin configuration pages for the user_api app
"""
from django.contrib import admin
from django.conf.urls import url
from django.contrib import admin, messages
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.utils.html import format_html
from django.utils.translation import ugettext as _
from openedx.core.djangoapps.user_api.accounts.forms import RetirementQueueDeletionForm
from .models import UserRetirementPartnerReportingStatus, RetirementState, UserRetirementStatus, UserRetirementRequest
......@@ -24,11 +32,110 @@ class UserRetirementStatusAdmin(admin.ModelAdmin):
"""
Admin interface for the UserRetirementStatus model.
"""
list_display = ('user', 'original_username', 'current_state', 'modified')
list_display = ('user', 'original_username', 'current_state', 'modified', 'retirement_actions')
list_filter = ('current_state',)
raw_id_fields = ('user',)
search_fields = ('original_username', 'retired_username', 'original_email', 'retired_email', 'original_name')
def cancel_retirement(self, request, retirement_id):
"""
Executed when the admin clicks the "Cancel" button on a UserRetirementStatus row,
this handles the confirmation view form, top level error handling, and permissions.
"""
if not request.user.has_perm('user_api.change_userretirementstatus'):
return HttpResponseForbidden(_("Permission Denied"))
retirement = self.get_object(request, retirement_id)
redirect_url = reverse(
'admin:user_api_userretirementstatus_changelist',
current_app=self.admin_site.name,
)
if retirement is None:
self.message_user(request, _('Retirement does not exist!'), level=messages.ERROR)
return HttpResponseRedirect(redirect_url)
if request.method != 'POST':
form = RetirementQueueDeletionForm()
else:
form = RetirementQueueDeletionForm(request.POST)
if form.is_valid():
try:
form.save(retirement)
self.message_user(request, _('Success'))
return HttpResponseRedirect(redirect_url)
except ValidationError:
# An exception in form.save will display errors on the form page
pass
context = self.admin_site.each_context(request)
context['opts'] = self.model._meta
context['form'] = form
context['retirement'] = retirement
return TemplateResponse(
request,
'admin/user_api/accounts/cancel_retirement_action.html',
context,
)
def get_urls(self):
"""
Adds our custom URL to the admin
"""
urls = super(UserRetirementStatusAdmin, self).get_urls()
custom_urls = [
url(
r'^(?P<retirement_id>.+)/cancel_retirement/$',
self.admin_site.admin_view(self.cancel_retirement),
name='cancel-retirement',
),
]
return custom_urls + urls
def retirement_actions(self, obj):
"""
Creates the HTML button in the admin for cancelling retirements,
but only if the row is in the right state.
"""
try:
if obj.current_state.state_name == 'PENDING':
return format_html(
'<a class="button" href="{}">{}</a>&nbsp;',
reverse('admin:cancel-retirement', args=[obj.pk]),
_('Cancel')
)
return format_html('')
except RetirementState.DoesNotExist:
# If the states don't exist, nothing to do here
return format_html('')
retirement_actions.short_description = _('Actions')
retirement_actions.allow_tags = True
def get_actions(self, request):
"""
Removes the default bulk delete option provided by Django,
it doesn't do what we need for this model.
"""
actions = super(UserRetirementStatusAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_add_permission(self, request):
"""
Removes the "add" button from admin
"""
return False
def has_delete_permission(self, request, obj=None):
"""
Removes the "delete" button from admin
"""
return False
class Meta(object):
model = UserRetirementStatus
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment