Skip to content

Commit

Permalink
Merge branch 'develop' into feature/270-delete-view-success-message
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
  • Loading branch information
d.choban committed Feb 28, 2018
2 parents 0530abf + 13f0d08 commit 2e4ab1b
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 70 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -13,6 +13,7 @@ Always reference the ticket number at the end of the issue description.

- Search form JS submitting selector - [#248][248]
- Float Label styling for a number of HTML5 inputs - [#247][247]
- confirm_links feature in ListViews now works properly - [#54][54].
- Fixed displaying success message after DeleteView - [#270][270]

## Changed
Expand All @@ -27,6 +28,7 @@ Always reference the ticket number at the end of the issue description.

[248]: //github.com/sanoma/django-arctic/issues/248
[247]: //github.com/sanoma/django-arctic/issues/247
[54]: //github.com/sanoma/django-arctic/issues/54
[257]: //github.com/sanoma/django-arctic/issues/257
[265]: //github.com/sanoma/django-arctic/issues/265
[259]: //github.com/sanoma/django-arctic/issues/259
Expand Down
5 changes: 5 additions & 0 deletions arctic/generics.py
Expand Up @@ -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):
"""
Expand All @@ -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,
Expand Down
35 changes: 29 additions & 6 deletions arctic/mixins.py
Expand Up @@ -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

Expand Down Expand Up @@ -497,9 +498,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('"', '"') 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)
Expand All @@ -515,11 +539,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):
Expand Down
1 change: 1 addition & 0 deletions arctic/static/arctic/config.yml
Expand Up @@ -53,5 +53,6 @@ PATHS:
- "src/assets/js/components/widgets.js"
- "src/assets/js/components/sortable.js"
- "src/assets/js/components/float_label.js"
- "src/assets/js/components/confirm_dialog.js"
- "src/assets/js/!(app).js"
- "src/assets/js/app.js"
4 changes: 2 additions & 2 deletions arctic/static/arctic/dist/assets/css/arctic.css

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion arctic/static/arctic/dist/assets/js/app.js

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions arctic/static/arctic/src/assets/js/components/confirm_dialog.js
@@ -0,0 +1,11 @@
$(document).ready(function() {
$('#confirm-dialog').on('show.bs.modal', function (event) {
var modal = $(this)
var button = $(event.relatedTarget) // Button that triggered the modal
modal.find('.modal-title').text(button.data('confirm-title'));
modal.find('.modal-body').text(button.data('confirm-message'));
modal.find('.modal-footer .confirm-cancel').text(button.data('confirm-cancel'))
modal.find('.modal-footer .confirm-ok').text(button.data('confirm-ok'))
modal.find('.modal-footer .confirm-ok').prop('href', button.prop('href'));
});
});
2 changes: 1 addition & 1 deletion arctic/static/arctic/src/assets/scss/_custom.scss
Expand Up @@ -738,7 +738,7 @@ $modal-backdrop-bg: $black !default;
$modal-backdrop-opacity: .5 !default;
$modal-header-border-color: $gray-lighter !default;
$modal-footer-border-color: $modal-header-border-color !default;
$modal-header-border-width: $modal-content-border-width !default;
$modal-header-border-width: 0 !default;
$modal-footer-border-width: $modal-header-border-width !default;
$modal-header-padding: 15px !default;

Expand Down
91 changes: 38 additions & 53 deletions arctic/templates/arctic/partials/base_data_table.html
Expand Up @@ -128,32 +128,9 @@ <h4 class="arctic-card__title">
{% for row in list_items %}
<tr>
{% for column in row %}
{% if column.confirm %}
<div class="modal fade" id="modal{{ column.value }}" tabindex="-1" role="dialog" aria-labelledby="modal{{ column.value }}Label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">Confirm your action</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{{ column.confirm|lookup:'message' }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ column.confirm|lookup:'cancel' }}</button>
<a class="btn btn-primary" href="{{ column.url }}" onclick="$('#modal{{ column.value }}').modal('hide')">{{ column.confirm|lookup:'yes' }}</a>
</div>
</div>
</div>
</div>
{% endif %}
{% if column.type == 'field' %}
<td {% if column.class %}class="{{ column.class }}"{%endif%}>
{% if column.confirm %}
<a data-toggle="modal" data-target="#modal{{ column.value }}">
{% elif column.url %}
{% if column.url %}
<a href="{{ column.url }}"{% if list_items.0.0.type == 'sorting' %}style="display:block;"{% endif %}>
{% endif %}
{% if column.value|typename != 'list' %}
Expand All @@ -172,35 +149,21 @@ <h5 class="modal-title" id="modalLabel">Confirm your action</h5>
{% block list_actions %}
<div class="list-actions">
{% for link in column.actions %}
{% if link.confirm %}
<div class="modal fade" id="modal{{ link.label }}" tabindex="-1" role="dialog" aria-labelledby="modal{{ link.label }}Label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirm your action</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
{{ link.confirm|lookup:'message' }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ link.confirm|lookup:'cancel' }}</button>
<a class="btn btn-primary" href="{{ link.url }}" onclick="$('#modal{{ link.value }}').modal('hide')">{{ link.confirm|lookup:'yes' }}</a>
</div>
</div>
</div>
</div>
<a data-toggle="modal" class="action-{{ link.label }} btn btn-secondary btn-sm show-on-hover" data-target="#modal{{ link.label }}" title=" 2{{ link.label|capfirst }}">
{% elif not link.confirm %}
<a href="{{ link.url }}" class="action-{{ link.label }} btn btn-secondary btn-sm show-on-hover" title="{{ link.label|capfirst }}">
{% endif %}
{% if link.icon %}
<i class="fa {{ link.icon }} fa-lg"></i>
{% else %}
{{ link.label|capfirst }}
{% endif %}
<a href="{{ link.url }}" class="action-{{ link.label }} btn btn-secondary btn-sm show-on-hover" title="{{ link.label|capfirst }}"
{% if link.confirm %}
data-toggle="modal"
data-target="#confirm-dialog"
data-confirm-title="{{ link.confirm.title }}"
data-confirm-message="{{ link.confirm.message }}"
data-confirm-ok="{{ link.confirm.ok }}"
data-confirm-cancel="{{ link.confirm.cancel }}"
{% endif %}
>
{% if link.icon %}
<i class="fa {{ link.icon }} fa-lg"></i>
{% else %}
{{ link.label|capfirst }}
{% endif %}
</a>
{% endfor %}
<div class="list-actions-placeholder"></div>
Expand Down Expand Up @@ -231,4 +194,26 @@ <h3 class="col text-center">{% trans 'No result...' %}</h3>
</div>
{% endblock %}

{% block confirm_dialog %}
<div class="modal fade" id="confirm-dialog" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel"></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary confirm-cancel" data-dismiss="modal">Cancel</button>
<a href="#" role="button" class="btn btn-primary confirm-ok">OK</a>
</div>
</div>
</div>
</div>
{% endblock %}

{% block extra_data %}{% endblock %}
14 changes: 13 additions & 1 deletion docs/reference.md
Expand Up @@ -339,7 +339,19 @@ links or, if only one tool link set, it would be use as default icon.

### `confirm_links`

dictionary as `{'url_field': {'message': 'Would you like to continue?', 'yes': 'Yes', 'cancel': 'No'}}'` which wraps every `url_field` displayed on a `ListView` with a confirmation dialog.
Dictionary of named urls that will display a confirmation dialog. The format is:

{'named_url': {
'title': 'Delete "{{ field_name }}"',
'message': 'Would you like to delete this?',
'ok': 'Delete',
'cancel': 'Cancel'},
...
}

Both `title` and `message` can contain field names wrapped as django template
variables, which will be parsed into the field value for the row instance.
Currently `confirm_links` work only on the `action_links` area.

### `advanced_search_form_class`

Expand Down
9 changes: 3 additions & 6 deletions example/articles/views.py
Expand Up @@ -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):
Expand Down

0 comments on commit 2e4ab1b

Please sign in to comment.