diff --git a/adminsortable/admin.py b/adminsortable/admin.py index 031ac0b..2def272 100755 --- a/adminsortable/admin.py +++ b/adminsortable/admin.py @@ -27,8 +27,9 @@ from django.http import HttpResponse from django.shortcuts import render from django.template.defaultfilters import capfirst -from adminsortable.utils import get_is_sortable, check_model_is_sortable +from adminsortable.fields import SortableForeignKey from adminsortable.models import SortableMixin +from adminsortable.utils import get_is_sortable, check_model_is_sortable STATIC_URL = settings.STATIC_URL @@ -145,9 +146,17 @@ class SortableAdmin(SortableAdminBase, ModelAdmin): # Legacy support for 'sortable_by' defined as a model property sortable_by_property = getattr(self.model, 'sortable_by', None) - # `sortable_by` defined as a SortableForeignKey - sortable_by_fk = self.model.sortable_foreign_key - sortable_by_class_is_sortable = check_model_is_sortable(sortable_by_fk) + # see if our model is sortable by a SortableForeignKey field + # and that the number of objects available is >= 2 + sortable_by_fk = None + sortable_by_field_name = None + sortable_by_class_is_sortable = False + + for field in self.model._meta.fields: + if isinstance(field, SortableForeignKey): + sortable_by_fk = field.rel.to + sortable_by_field_name = field.name.lower() + sortable_by_class_is_sortable = sortable_by_fk.objects.count() >= 2 if sortable_by_property: # backwards compatibility for < 1.1.1, where sortable_by was a @@ -165,10 +174,9 @@ class SortableAdmin(SortableAdminBase, ModelAdmin): elif sortable_by_fk: # get sortable by properties from the SortableForeignKey # field - supported in 1.3+ - sortable_by_class_display_name = sortable_by_fk.rel.to \ - ._meta.verbose_name_plural - sortable_by_class = sortable_by_fk.rel.to - sortable_by_expression = sortable_by_fk.name.lower() + sortable_by_class_display_name = sortable_by_fk._meta.verbose_name_plural + sortable_by_class = sortable_by_fk + sortable_by_expression = sortable_by_field_name else: # model is not sortable by another model diff --git a/adminsortable/static/adminsortable/css/admin.sortable.css b/adminsortable/static/adminsortable/css/admin.sortable.css index 7af1b1f..e03ef81 100644 --- a/adminsortable/static/adminsortable/css/admin.sortable.css +++ b/adminsortable/static/adminsortable/css/admin.sortable.css @@ -42,7 +42,16 @@ margin-bottom: 0; } +.sortable-help-text { + color: #999; + font-size: 13px; +} + .sortable a:hover { color: #003366; } + +.sortable .fa { + margin-right: 7px; +} diff --git a/adminsortable/static/adminsortable/css/admin.sortable.inline.css b/adminsortable/static/adminsortable/css/admin.sortable.inline.css index 44f7e70..cbde4e8 100644 --- a/adminsortable/static/adminsortable/css/admin.sortable.inline.css +++ b/adminsortable/static/adminsortable/css/admin.sortable.inline.css @@ -1,3 +1,17 @@ .sortable.has_original { cursor: move; } + +.sortable .inline-related .module.aligned .fa, +.sortable.inline-group .module .fa { + display: block; + float: left; +} + +.sortable .inline-related .module.aligned .fa { + margin: 9px 10px 0 0; +} + +.sortable.inline-group .module .fa { + margin: 34px -10px 0 10px; +} diff --git a/adminsortable/static/adminsortable/js/admin.sortable.js b/adminsortable/static/adminsortable/js/admin.sortable.js index b854f52..cca28cb 100644 --- a/adminsortable/static/adminsortable/js/admin.sortable.js +++ b/adminsortable/static/adminsortable/js/admin.sortable.js @@ -8,17 +8,36 @@ items : 'li', stop : function(event, ui) { - var indexes = []; - ui.item.parent().children('li').each(function(i) + var indexes = [], + lineItems = ui.item.parent().find('> li'); + + lineItems.each(function(i) { indexes.push($(this).find(':hidden[name="pk"]').val()); }); + $.ajax({ url: ui.item.find('a.admin_sorting_url').attr('href'), type: 'POST', data: { indexes: indexes.join(',') }, success: function() { + // set icons based on position + lineItems.each(function(index, element) { + var icon = $(element).find('> a .fa'); + icon.removeClass('fa-sort-desc fa-sort-asc fa-sort'); + + if (index === 0) { + icon.addClass('fa fa-sort-desc'); + } + else if (index == lineItems.length - 1) { + icon.addClass('fa fa-sort-asc'); + } + else { + icon.addClass('fa fa-sort'); + } + }); + ui.item.effect('highlight', {}, 1000); } }); diff --git a/adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js b/adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js index 3b32b7e..4afbea3 100644 --- a/adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js +++ b/adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js @@ -41,7 +41,24 @@ data: { indexes : indexes.join(',') }, success: function() { var fieldsets = ui.item.find('fieldset'), - highlightedSelector = fieldsets.filter('.collapsed').length === fieldsets.length ? 'h3' : '.form-row'; + highlightedSelector = fieldsets.filter('.collapsed').length === fieldsets.length ? 'h3' : '.form-row', + icons = ui.item.parent().find(highlightedSelector).find('.fa'); + + // set icons based on position + icons.removeClass('fa-sort-desc fa-sort-asc fa-sort'); + icons.each(function(index, element) { + var icon = $(element); + if (index === 0) { + icon.addClass('fa fa-sort-desc'); + } + else if (index == icons.length - 1) { + icon.addClass('fa fa-sort-asc'); + } + else { + icon.addClass('fa fa-sort'); + } + }); + ui.item.find(highlightedSelector).effect('highlight', {}, 1000); } }); diff --git a/adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js b/adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js index 44c9fe8..debd654 100644 --- a/adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js +++ b/adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js @@ -38,7 +38,23 @@ type: 'POST', data: { indexes : indexes.join(',') }, success: function() { - //highlight sorted row, then re-stripe table + // set icons based on position + var icons = ui.item.parent().find('.fa'); + icons.removeClass('fa-sort-desc fa-sort-asc fa-sort'); + icons.each(function(index, element) { + var icon = $(element); + if (index === 0) { + icon.addClass('fa fa-sort-desc'); + } + else if (index == icons.length - 1) { + icon.addClass('fa fa-sort-asc'); + } + else { + icon.addClass('fa fa-sort'); + } + }); + + // highlight sorted row, then re-stripe table ui.item.effect('highlight', {}, 1000); tabular_inline_rows.removeClass('row1 row2'); $('.tabular table tbody tr:odd').addClass('row2'); diff --git a/adminsortable/templates/adminsortable/change_form.html b/adminsortable/templates/adminsortable/change_form.html index 3a4e922..0f3fd76 100644 --- a/adminsortable/templates/adminsortable/change_form.html +++ b/adminsortable/templates/adminsortable/change_form.html @@ -24,6 +24,7 @@ {{ block.super }} {% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %} + {% endif %} {% endblock %} diff --git a/adminsortable/templates/adminsortable/change_list.html b/adminsortable/templates/adminsortable/change_list.html index f8dfbc9..7b6e83e 100644 --- a/adminsortable/templates/adminsortable/change_list.html +++ b/adminsortable/templates/adminsortable/change_list.html @@ -4,6 +4,7 @@ {% block extrastyle %} {{ block.super }} + {% endblock %} @@ -40,8 +41,8 @@ {% blocktrans with opts.verbose_name_plural|capfirst as model %}Drag and drop {{ model }} to change their order.{% endblocktrans %} {% endif %} - {% if sortable_by_class.is_sortable %} -
+ {% if sortable_by_class_is_sortable %} +
{% blocktrans %}You may also drag and drop {{ sortable_by_class_display_name }} to change their order.{% endblocktrans %}
{% endif %} diff --git a/adminsortable/templates/adminsortable/edit_inline/stacked-1.5.x.html b/adminsortable/templates/adminsortable/edit_inline/stacked-1.5.x.html index bc7ce69..c133fe6 100644 --- a/adminsortable/templates/adminsortable/edit_inline/stacked-1.5.x.html +++ b/adminsortable/templates/adminsortable/edit_inline/stacked-1.5.x.html @@ -12,7 +12,7 @@ {% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %} {% for fieldset in inline_admin_form %} - {% include "admin/includes/fieldset.html" %} + {% include "admin/includes/fieldset.html" with inline_admin_form_forloop=forloop.parentloop %} {% endfor %} {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %} {{ inline_admin_form.fk_field.field }} diff --git a/adminsortable/templates/adminsortable/edit_inline/stacked.html b/adminsortable/templates/adminsortable/edit_inline/stacked.html index 0bf7d7b..ff45712 100644 --- a/adminsortable/templates/adminsortable/edit_inline/stacked.html +++ b/adminsortable/templates/adminsortable/edit_inline/stacked.html @@ -12,13 +12,13 @@ {% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %} {% for fieldset in inline_admin_form %} - {% include "admin/includes/fieldset.html" %} + {% include "adminsortable/shared/fieldset.html" with inline_admin_form_forloop=forloop.parentloop initial_forms_count=inline_admin_formset.formset.management_form.initial.INITIAL_FORMS %} {% endfor %} - {% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %} - {{ inline_admin_form.fk_field.field }} {% if inline_admin_form.original %} {% endif %} + {% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %} + {{ inline_admin_form.fk_field.field }} {% endfor %} diff --git a/adminsortable/templates/adminsortable/edit_inline/tabular-1.5.x.html b/adminsortable/templates/adminsortable/edit_inline/tabular-1.5.x.html index 34555ee..30f1772 100644 --- a/adminsortable/templates/adminsortable/edit_inline/tabular-1.5.x.html +++ b/adminsortable/templates/adminsortable/edit_inline/tabular-1.5.x.html @@ -48,6 +48,7 @@ {% for line in fieldset %} {% for field in line %}{{ field.contents }}
{% else %} diff --git a/adminsortable/templates/adminsortable/edit_inline/tabular.html b/adminsortable/templates/adminsortable/edit_inline/tabular.html index 247818e..9554f0d 100644 --- a/adminsortable/templates/adminsortable/edit_inline/tabular.html +++ b/adminsortable/templates/adminsortable/edit_inline/tabular.html @@ -25,6 +25,11 @@{% if inline_admin_form.original %} {{ inline_admin_form.original }} diff --git a/adminsortable/templates/adminsortable/shared/fieldset.html b/adminsortable/templates/adminsortable/shared/fieldset.html new file mode 100644 index 0000000..89659ae --- /dev/null +++ b/adminsortable/templates/adminsortable/shared/fieldset.html @@ -0,0 +1,35 @@ +{# overrides admin/includes/fieldset.html: https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/includes/fieldset.html #} +
diff --git a/adminsortable/templates/adminsortable/shared/list_items.html b/adminsortable/templates/adminsortable/shared/list_items.html index bfc21a6..29df030 100644 --- a/adminsortable/templates/adminsortable/shared/list_items.html +++ b/adminsortable/templates/adminsortable/shared/list_items.html @@ -3,7 +3,7 @@ {% for object in list_objects %}