Repository: dpgmediamagazines/django-arctic

Issue:
Improve the confirm delete dialog
It should be a modal dialog, with "Delete" instead of "Confirm" as the action button



Discussion:
Add translation texts
The need for a confirm dialog has a few use cases beyond the delete action, so it would be useful to have a generic solution to optionally present a dialog for any link in a view that needs it.
Proposed interface:
in `View`:

     confirm_links = {'named_url': ('Are you sure you want to do this?', 'No', 'Yes'), ...}

the effect would be that whenever there is a url match for `action_links`, `field_links` or `tool_links` a confirmation dialog will be presented; the dialog content is defined in a tuple with the question text, a button to dismiss the dialog and a button to open the link.


Resolving patch:
diff --git a/arctic/generics.py b/arctic/generics.py
--- a/arctic/generics.py
+++ b/arctic/generics.py
@@ -747,6 +747,7 @@ def get_context_data(self, **kwargs):
 
 class DeleteView(SuccessMessageMixin, View, base.DeleteView):
     template_name = 'arctic/base_confirm_delete.html'
+    redirect = True
 
     def get(self, request, *args, **kwargs):
         """
@@ -765,6 +766,10 @@ def get(self, request, *args, **kwargs):
             protected_objects = e.protected_objects
             can_delete = False
 
+        if can_delete and self.redirect:
+            self.delete(request, *args, **kwargs)
+            return redirect(self.success_url)
+
         context = self.get_context_data(object=self.object,
                                         can_delete=can_delete,
                                         collector_message=collector_message,
diff --git a/arctic/mixins.py b/arctic/mixins.py
--- a/arctic/mixins.py
+++ b/arctic/mixins.py
@@ -7,6 +7,7 @@
 from django.conf import settings
 from django.contrib import messages
 from django.core.exceptions import (ImproperlyConfigured, PermissionDenied)
+from django.template import (Template, Context)
 from django.urls import reverse
 from django.utils import six
 
@@ -488,9 +489,32 @@ def get_field_classes(self, obj):
                 field_classes[field_name] = get_field_name_classes(obj)
         return field_classes
 
+    def get_confirm_link(self, url, obj):
+        """
+        Returns the metadata for a link that needs to be confirmed, if it
+        exists, it also parses the message and title of the url to include
+        row field data if needed.
+        """
+        try:
+            if type(obj) != dict:
+                obj = vars(obj)
+            link = {key: value.replace('"', '&quot;') for (key, value) in
+                    self.confirm_links[url].items()}
+            link['message'] = Template(link['message']).render(Context(obj))
+            link['title'] = Template(link['title']).render(Context(obj))
+            link['ok']  # this triggers a KeyError exception if not existent
+            link['cancel']
+            return link
+        except KeyError as e:
+            raise ImproperlyConfigured(
+                'confirm_links requires a dictionary with \'message\', '
+                '\'title\', \'ok\' and \'cancel\' strings, the named url \'' +
+                url + '\' misses ' + str(e))
+        except AttributeError:
+            return None
+
     def _get_field_actions(self, obj):
         all_actions = self.get_action_links()
-        has_confirm_links = hasattr(self, 'confirm_links')
         get_field_actions = getattr(self, 'get_field_actions', None)
         if get_field_actions:
             field_actions = get_field_actions(obj)
@@ -506,11 +530,10 @@ def _get_field_actions(self, obj):
                 actions.append({'label': field_action['label'],
                                 'icon': field_action['icon'],
                                 'url': self._reverse_field_link(
-                                    field_action['url'], obj)})
-                field_url_name = field_action['url']
-                if has_confirm_links and field_url_name in self.confirm_links:
-                    actions[0].update({'confirm':
-                                      self.confirm_links[field_url_name]})
+                                    field_action['url'], obj),
+                                'confirm': self.get_confirm_link(
+                                    field_action['url'], obj),
+                                })
             return {'type': 'actions', 'actions': actions}
 
     def _get_allowed_field_actions(self, field_actions, all_actions):
diff --git a/example/articles/views.py b/example/articles/views.py
--- a/example/articles/views.py
+++ b/example/articles/views.py
@@ -138,13 +138,10 @@ class CategoryListView(ListView):
     ]
     confirm_links = {
         'articles:category-delete': {
+            'title': _('Delete "{{ name }}"'),
             'message': _('Are you sure you want to delete this?'),
-            'yes': _('Yes'),
-            'cancel': _('No')},
-        'articles:category-detail': {
-            'message': _('Are you sure you want to proceed'),
-            'yes': _('Yes'),
-            'cancel': _('No')}}
+            'ok': _('Delete'),
+            'cancel': _('Cancel')}}
 
 
 class CategoryArticlesListView(ArticleListView):


Test patch: