From d1911519edcc4f6dd98c359b952f7eec083c7948 Mon Sep 17 00:00:00 2001 From: Brandon Taylor Date: Wed, 2 Nov 2016 21:29:31 -0400 Subject: [PATCH 1/2] Added version check for 1.7 to create context dict. --- adminsortable/admin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/adminsortable/admin.py b/adminsortable/admin.py index f67505a..7257a34 100644 --- a/adminsortable/admin.py +++ b/adminsortable/admin.py @@ -219,7 +219,11 @@ class SortableAdmin(SortableAdminBase, ModelAdmin): except AttributeError: verbose_name_plural = opts.verbose_name_plural - context = self.admin_site.each_context(request) + if VERSION <= (1, 7): + context = {} + else: + context = self.admin_site.each_context(request) + context.update({ 'title': u'Drag and drop {0} to change display order'.format( capfirst(verbose_name_plural)), From e35f36b25a968aa8d2ade04b2263fe1169a4ccb2 Mon Sep 17 00:00:00 2001 From: Brandon Taylor Date: Mon, 18 Jun 2018 11:40:24 -0400 Subject: [PATCH 2/2] Refactored sorting JS files to be includes so that server-side variables may be passed to them. Added 'after_sorting_js_callback_name' attribute to SortableAdminBase. Added callback to be executed after sorting for each of the possible sorting scenarios. Added custom template examples to add a callback to be executed when sorting is finished. --- adminsortable/admin.py | 8 +- .../adminsortable/admin.sortable.html} | 101 ++++++------ .../templates/adminsortable/change_form.html | 6 +- .../templates/adminsortable/change_list.html | 23 ++- .../admin.sortable.stacked.inlines.html} | 148 +++++++++--------- .../admin.sortable.tabular.inlines.html} | 144 +++++++++-------- sample_project/database/test_project.sqlite | Bin 278528 -> 278528 bytes sample_project/samples/admin.py | 3 + .../adminsortable/custom_change_form.html | 15 ++ .../adminsortable/custom_change_list.html | 15 ++ 10 files changed, 270 insertions(+), 193 deletions(-) rename adminsortable/{static/adminsortable/js/admin.sortable.js => templates/adminsortable/admin.sortable.html} (83%) rename adminsortable/{static/adminsortable/js/admin.sortable.stacked.inlines.js => templates/adminsortable/edit_inline/admin.sortable.stacked.inlines.html} (89%) rename adminsortable/{static/adminsortable/js/admin.sortable.tabular.inlines.js => templates/adminsortable/edit_inline/admin.sortable.tabular.inlines.html} (89%) create mode 100644 sample_project/templates/adminsortable/custom_change_form.html create mode 100644 sample_project/templates/adminsortable/custom_change_list.html diff --git a/adminsortable/admin.py b/adminsortable/admin.py index 3bad43e..612947d 100644 --- a/adminsortable/admin.py +++ b/adminsortable/admin.py @@ -32,6 +32,8 @@ class SortableAdminBase(object): change_form_template_extends = 'admin/change_form.html' change_list_template_extends = 'admin/change_list.html' + after_sorting_js_callback_name = None + def changelist_view(self, request, extra_context=None): """ If the model that inherits Sortable has more than one object, @@ -215,7 +217,8 @@ class SortableAdmin(SortableAdminBase, ModelAdmin): 'sortable_by_class_is_sortable': sortable_by_class_is_sortable, 'sortable_by_class_display_name': sortable_by_class_display_name, 'jquery_lib_path': jquery_lib_path, - 'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken') + 'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken'), + 'after_sorting_js_callback_name': self.after_sorting_js_callback_name }) return render(request, self.sortable_change_list_template, context) @@ -238,7 +241,8 @@ class SortableAdmin(SortableAdminBase, ModelAdmin): 'change_form_template_extends': self.change_form_template_extends, 'has_sortable_tabular_inlines': self.has_sortable_tabular_inlines, 'has_sortable_stacked_inlines': self.has_sortable_stacked_inlines, - 'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken') + 'csrf_cookie_name': getattr(settings, 'CSRF_COOKIE_NAME', 'csrftoken'), + 'after_sorting_js_callback_name': self.after_sorting_js_callback_name }) return super(SortableAdmin, self).change_view(request, object_id, diff --git a/adminsortable/static/adminsortable/js/admin.sortable.js b/adminsortable/templates/adminsortable/admin.sortable.html similarity index 83% rename from adminsortable/static/adminsortable/js/admin.sortable.js rename to adminsortable/templates/adminsortable/admin.sortable.html index ad4b099..15a42a1 100644 --- a/adminsortable/static/adminsortable/js/admin.sortable.js +++ b/adminsortable/templates/adminsortable/admin.sortable.html @@ -1,47 +1,54 @@ -(function($){ - - $(function() { - jQuery('.sortable').sortable({ - axis : 'y', - containment : 'parent', - tolerance : 'pointer', - items : 'li', - stop : function(event, ui) { - 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.admin_sorting_url .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); - } - }); - } - }).click(function(e){ - e.preventDefault(); - }); - }); - -})(django.jQuery); + diff --git a/adminsortable/templates/adminsortable/change_form.html b/adminsortable/templates/adminsortable/change_form.html index 65763cb..c60b413 100644 --- a/adminsortable/templates/adminsortable/change_form.html +++ b/adminsortable/templates/adminsortable/change_form.html @@ -7,17 +7,17 @@ {% url 'admin:jsi18n' as jsi18nurl %} {% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %} - + {% include 'adminsortable/csrf/jquery.django-csrf.html' with csrf_cookie_name=csrf_cookie_name %} {% endif %} {% if has_sortable_tabular_inlines %} - + {% include 'adminsortable/edit_inline/admin.sortable.stacked.inlines.html' with after_sorting_js_callback_name=after_sorting_js_callback_name %} {% endif %} {% if has_sortable_stacked_inlines %} - + {% include 'adminsortable/edit_inline/admin.sortable.tabular.inlines.html' with after_sorting_js_callback_name=after_sorting_js_callback_name %} {% endif %} {% endblock %} diff --git a/adminsortable/templates/adminsortable/change_list.html b/adminsortable/templates/adminsortable/change_list.html index 3be48ab..5fc6ca2 100644 --- a/adminsortable/templates/adminsortable/change_list.html +++ b/adminsortable/templates/adminsortable/change_list.html @@ -21,14 +21,31 @@ {% endblock %} {% block extrahead %} -{{ block.super }} -{{ media.js }} +{{ block.super }} +{{ media.js }} {% include 'adminsortable/csrf/jquery.django-csrf.html' with csrf_cookie_name=csrf_cookie_name %} - +{% include 'adminsortable/admin.sortable.html' with after_sorting_js_callback_name=after_sorting_js_callback_name %} + + {% endblock %} {% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-list{% endblock %} diff --git a/adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js b/adminsortable/templates/adminsortable/edit_inline/admin.sortable.stacked.inlines.html similarity index 89% rename from adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js rename to adminsortable/templates/adminsortable/edit_inline/admin.sortable.stacked.inlines.html index b6e21f4..f414272 100644 --- a/adminsortable/static/adminsortable/js/admin.sortable.stacked.inlines.js +++ b/adminsortable/templates/adminsortable/edit_inline/admin.sortable.stacked.inlines.html @@ -1,70 +1,78 @@ -(function($){ - - $(function() { - var sorting_urls = $(':hidden[name="admin_sorting_url"]'); - if (sorting_urls.length > 0) - { - var sortable_inline_groups = sorting_urls.closest('.inline-group') - var sortable_inline_rows = sortable_inline_groups.find('.inline-related'); - - sortable_inline_groups.addClass('sortable') - sortable_inline_rows.addClass('sortable'); - - sortable_inline_groups.sortable({ - axis : 'y', - containment : 'parent', - create: function(event, ui) { - $('.inline-related :checkbox').unbind(); - }, - tolerance : 'pointer', - items : '.inline-related', - stop : function(event, ui) - { - if ($('.inline-deletelink').length > 0) { - $(ui.sender).sortable('cancel'); - alert($('#localized_save_before_reorder_message').val()); - return false; - } - - var indexes = []; - ui.item.parent().children('.inline-related').each(function(i) - { - var index_value = $(this).find(':hidden[name$="-id"]').val(); - if (index_value !== "" && index_value !== undefined) { - indexes.push(index_value); - } - }); - - $.ajax({ - url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), - type: 'POST', - data: { indexes : indexes.join(',') }, - success: function() { - var fieldsets = ui.item.find('fieldset'), - highlightedSelector = fieldsets.filter('.collapsed').length === fieldsets.length ? 'h3' : '.form-row', - icons = ui.item.parent().find('h3 > .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); - } - }); - } - }); - } - }); - -})(django.jQuery); + diff --git a/adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js b/adminsortable/templates/adminsortable/edit_inline/admin.sortable.tabular.inlines.html similarity index 89% rename from adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js rename to adminsortable/templates/adminsortable/edit_inline/admin.sortable.tabular.inlines.html index 376df13..d993b39 100644 --- a/adminsortable/static/adminsortable/js/admin.sortable.tabular.inlines.js +++ b/adminsortable/templates/adminsortable/edit_inline/admin.sortable.tabular.inlines.html @@ -1,69 +1,77 @@ -(function($){ - - $(function() { - var sorting_urls = $(':hidden[name="admin_sorting_url"]'); - if (sorting_urls.length) - { - var sortable_inline_group = sorting_urls.closest('.inline-group'); - var tabular_inline_rows = sortable_inline_group.find('.tabular table tbody tr'); - - tabular_inline_rows.addClass('sortable'); - - sortable_inline_group.find('.tabular.inline-related').sortable({ - axis : 'y', - containment : 'parent', - create: function(event, ui) { - $('td.delete :checkbox').unbind(); - }, - tolerance : 'pointer', - items : 'tr:not(.add-row)', - stop : function(event, ui) { - if ($('.inline-deletelink').length > 0) { - $(ui.sender).sortable('cancel'); - alert($('#localized_save_before_reorder_message').val()); - return false; - } - - var indexes = []; - ui.item.parent().children('tr').each(function(i) - { - var index_value = $(this).find('.original :input:first').val(); + diff --git a/sample_project/database/test_project.sqlite b/sample_project/database/test_project.sqlite index d439e4aa7e01445f09b8dc591f1317907df46d85..944cf225d53fa5197b12a06d2813064d15e8bac5 100644 GIT binary patch delta 1767 zcmah}ZA?>F7{2G6TcPN^F9phnsJ$|ljUa9By)FH4x*?Scu~fE#qw4TVE2S;8&>FDD z2!1SaOZ-T;-Tg6|ne4~hWDJ*PF>cBHW3m_}Zt5~Kjr;g9li|k_|CqSb7H~#0?~gaR z&wZZfyyv~oIb&nGu`%6|YIO1Fl4i|C##nh_GH}e$z+Ga>xq)*28@?9K!VrHIK7gg* z_`NMv7v-CQ_>kyrr!M=7o;_&I>N%cY0=cl!VJTw-!m;)T)LRl zql7XLj|LMx@!?oF*qbC3ERm6VZvd4}T``GU3o(D10Y86wO1JeBe$RLv=9uxiCT%q* zYqd>Wd|M>2UFu1M6v^6HE1I)UtveKLZAq;64MjWG*RG2zy>EphmZZF4RHxbR?h3W1I?UdUEn$z;G1BhxSiG)osofO~ zdEFkf-`8qxcLlI?h3aKn&(F*Ii8HnBFa{~ZSP8yYhJxIgM_KS{$4yuDq%=1 zIDwXx?t|Sh0z+^Orr`(p5DvpZx?=~Zx4f7w(^YB+Lb{4vEzecGdT;{mq6P=lf-g~B zA*gT^-iHHJ<;kfur8yDKiEvJY^_gSep}t~LiFInhWvU_{leh6C)=i1UKclMgrIket z7|?hSp(c4lK7WFYH>uNC(F%>=3yvn$=^Lm@Ex(2;SLfbqcJJPz!}Gt~E{GPVWOIt5 zvC$%1Wyg4JMcy;<9M3X!;wmcR*9+1qRlBuM$uw* zNYd(ZE$v)e|I{LzcGW0>Krm3_6m~t`WjZy;HX zvdwOB$eHU`(27Mg+!+QkaD)DaQ}A*v@t_w)6{|O9(5qBMdv8JNkR6lP0-3PjNYK1 zRZ=)d<|vBcECavN@-;{PF#-I^urPt(0Zh=)pQD`}2iGF3VXBa}J(dg#5-wpi%u5L6 z-*RzdNeOv^i8+iAYR+)9lRPo=;B}&Vqlm!${B-V9>))Y>C0azX1!o=|CWYn~kM9yG z5&&+|HcukB3n$?MoS|N6P;Wjay4OnB1&qE5p*AHF%%_wk*_l*RY&Oz)INxA#X@yqn ziw!hKmElO{E_E<-)SSRM4Ci15E>Y_VXa>YG%TcqE4EDu_cM2i~o=`+Pk7NhTz<&V1 IPbnnwFC_!%bN~PV delta 563 zcmXw#O=}ZT6o&7aJ4q&O=blUq24ZW*;-W$Gr8`B^Qb7=;S?H!HNoZm*m=D{4xC>SU z1+is>y9x#r6hEjng;Bat`U7GlEkr17iDaYDM7nU360Zi~a2N0MKAgiX7PVqgTRZ~k zrQu0Sn)naqR+1&JpS>oB)r^yUWXEw0Z{dA>f+KiYT~OEX9BZ)!c8%HC8TC7Es$VJr zy{uX!r-z;}>i+9i*D*J}0Q_qLMvSY0DT!?uZv#FT(d_eyO#WtSK9lHsva`9^OfFkUWec&woxEG7r-A>>(;)5LV-rHi-}RgCGUuN1)FM9e@%i~qy{g}UvDWadUztw6r#eP5FuR$%LdtqcBv zDR<9;<F+X9xj?H%}pok6qo z31%JCMH}2!6Is~tlA4V=oE#EYY>~esdNt%*Z5XoxHVHOG&_J`P*@VS2<~G`c;ApOM<_G* zBUBp~>$(KHB5orUJ+u3mDxv=?YgF&cI|MtpBU*Lj&w5ldJK_ncLZDdv$FM5sXXMq0 Gbm|YO)v!GP diff --git a/sample_project/samples/admin.py b/sample_project/samples/admin.py index ec18418..fb1acf1 100644 --- a/sample_project/samples/admin.py +++ b/sample_project/samples/admin.py @@ -83,6 +83,9 @@ class ProjectAdmin(SortableAdmin): NonSortableCreditInline, NonSortableNoteInline ] list_display = ['__str__', 'category'] + after_sorting_js_callback_name = 'afterSortCallback' + sortable_change_list_template = 'adminsortable/custom_change_list.html' + sortable_change_form_template = "adminsortable/custom_change_form.html" admin.site.register(Project, ProjectAdmin) diff --git a/sample_project/templates/adminsortable/custom_change_form.html b/sample_project/templates/adminsortable/custom_change_form.html new file mode 100644 index 0000000..84f706c --- /dev/null +++ b/sample_project/templates/adminsortable/custom_change_form.html @@ -0,0 +1,15 @@ +{% extends "adminsortable/change_form.html" %} + +{% block extrahead %} + {{ block.super }} + + +{% endblock %} diff --git a/sample_project/templates/adminsortable/custom_change_list.html b/sample_project/templates/adminsortable/custom_change_list.html new file mode 100644 index 0000000..3fbc2b6 --- /dev/null +++ b/sample_project/templates/adminsortable/custom_change_list.html @@ -0,0 +1,15 @@ +{% extends 'adminsortable/change_list.html' %} + +{% block extrahead %} + {{ block.super }} + + +{% endblock %}