From f2ed107b079b050950e2fc5f2b689ca553ae12f5 Mon Sep 17 00:00:00 2001 From: Julien Phalip Date: Sat, 24 Sep 2011 06:17:53 +0000 Subject: Simplified the admin changelist multi-sort interface specifically by removing the popup window, adding explicit tooltip help texts, improving the hover visual states and allowing all operations (i.e. removing a column from sorting and toggling the sorting with and without changing the sorting priority) to be actionable with just one click. Many thanks to Idan Gazit for the feedback and direction. Refs #16212. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16899 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/admin/static/admin/css/base.css | 89 +++++++++-------- django/contrib/admin/static/admin/css/rtl.css | 17 +--- .../contrib/admin/static/admin/img/arrow-down.gif | Bin 80 -> 0 bytes django/contrib/admin/static/admin/img/arrow-up.gif | Bin 838 -> 0 bytes django/contrib/admin/static/admin/img/icon_cog.gif | Bin 537 -> 0 bytes .../admin/static/admin/img/sorting-icons.gif | Bin 0 -> 369 bytes .../admin/templates/admin/change_list_results.html | 106 +++------------------ django/contrib/admin/templatetags/admin_list.py | 27 ++++-- docs/releases/1.4.txt | 13 ++- 9 files changed, 85 insertions(+), 167 deletions(-) delete mode 100644 django/contrib/admin/static/admin/img/arrow-down.gif delete mode 100644 django/contrib/admin/static/admin/img/arrow-up.gif delete mode 100644 django/contrib/admin/static/admin/img/icon_cog.gif create mode 100644 django/contrib/admin/static/admin/img/sorting-icons.gif diff --git a/django/contrib/admin/static/admin/css/base.css b/django/contrib/admin/static/admin/css/base.css index 89f2225c7c..5db94a7d25 100644 --- a/django/contrib/admin/static/admin/css/base.css +++ b/django/contrib/admin/static/admin/css/base.css @@ -309,77 +309,84 @@ tr.alt { /* SORTABLE TABLES */ +thead th { + padding: 0; + line-height: normal; +} + thead th a:link, thead th a:visited { color: #666; - display: block; } thead th.sorted { background: #c5c5c5 url(../img/nav-bg-selected.gif) top left repeat-x; } -table thead th.sorted a { - padding-right: 13px; +table thead th .text span { + padding: 2px 5px; + display:block; } -table thead th.ascending a { - background: url(../img/arrow-up.gif) right .4em no-repeat; +table thead th .text a { + display: block; + cursor: pointer; + padding: 2px 5px; } -table thead th.descending a { - background: url(../img/arrow-down.gif) right .4em no-repeat; +table thead th.sortable:hover { + background: white url(../img/nav-bg-reverse.gif) 0 -5px repeat-x; } -table thead th.sorted a span.text { - display: block; - float: left; - cursor: pointer; /* IE needs this */ +thead th.sorted a.sortremove { + visibility: hidden; } -table thead th.sorted a span.sortpos { - display: block; - float: right; - font-size: .6em; - text-align: right; - cursor: pointer; /* IE needs this */ +table thead th.sorted:hover a.sortremove { + visibility: visible; } -table thead th.sorted a img { - vertical-align: top; +table thead th.sorted .sortoptions { + display: block; + padding: 4px 5px 0 5px; + float: right; + text-align: right; } -table thead th.sorted a span.clear { - display: block; - clear: both; +table thead th.sorted .sortpriority { + font-size: .8em; + min-width: 12px; + text-align: center; + vertical-align: top; } -#sorting-popup-div { - display: none; - position: absolute; - background-color: white; - border: 1px solid #ddd; - z-index: 2000; /* more than filters on right */ +table thead th.sorted .sortoptions a { + width: 14px; + height: 12px; + display: inline-block; } -#sorting-popup-div table { - border-right: 0px; - border-left: 0px; +table thead th.sorted .sortoptions a.sortremove { + background: url(../img/sorting-icons.gif) -4px -5px no-repeat; } -#sorting-popup-div .reset { - text-align: center; +table thead th.sorted .sortoptions a.sortremove:hover { + background: url(../img/sorting-icons.gif) -4px -27px no-repeat; } -#sorting-popup-div .cancel { - font-size: 10px; - background: #e1e1e1 url(../img/nav-bg.gif) 0 50% repeat-x; - border-top: 1px solid #ddd; - text-align: center; +table thead th.sorted .sortoptions a.ascending { + background: url(../img/sorting-icons.gif) -5px -50px no-repeat; } -#sorting-popup-div .cancel a { - width: 100%; - display: block; +table thead th.sorted .sortoptions a.ascending:hover { + background: url(../img/sorting-icons.gif) -5px -72px no-repeat; +} + +table thead th.sorted .sortoptions a.descending { + background: url(../img/sorting-icons.gif) -5px -94px no-repeat; +} + +table thead th.sorted .sortoptions a.descending:hover { + background: url(../img/sorting-icons.gif) -5px -115px no-repeat; } /* ORDERABLE TABLES */ diff --git a/django/contrib/admin/static/admin/css/rtl.css b/django/contrib/admin/static/admin/css/rtl.css index fce6b1ab0e..029bf36f82 100644 --- a/django/contrib/admin/static/admin/css/rtl.css +++ b/django/contrib/admin/static/admin/css/rtl.css @@ -80,22 +80,7 @@ div.breadcrumbs { /* SORTABLE TABLES */ - -table thead th.sorted a { - padding-left: 13px; - padding-right: 0px; -} - -table thead th.ascending a, -table thead th.descending a { - background-position: left; -} - -table thead th.sorted a span.text { - float: right; -} - -table thead th.sorted a span.sortpos { +table thead th.sorted .sortoptions { float: left; } diff --git a/django/contrib/admin/static/admin/img/arrow-down.gif b/django/contrib/admin/static/admin/img/arrow-down.gif deleted file mode 100644 index a967b9fd55..0000000000 Binary files a/django/contrib/admin/static/admin/img/arrow-down.gif and /dev/null differ diff --git a/django/contrib/admin/static/admin/img/arrow-up.gif b/django/contrib/admin/static/admin/img/arrow-up.gif deleted file mode 100644 index 3fe4851399..0000000000 Binary files a/django/contrib/admin/static/admin/img/arrow-up.gif and /dev/null differ diff --git a/django/contrib/admin/static/admin/img/icon_cog.gif b/django/contrib/admin/static/admin/img/icon_cog.gif deleted file mode 100644 index e390ef2ef5..0000000000 Binary files a/django/contrib/admin/static/admin/img/icon_cog.gif and /dev/null differ diff --git a/django/contrib/admin/static/admin/img/sorting-icons.gif b/django/contrib/admin/static/admin/img/sorting-icons.gif new file mode 100644 index 0000000000..451aae5987 Binary files /dev/null and b/django/contrib/admin/static/admin/img/sorting-icons.gif differ diff --git a/django/contrib/admin/templates/admin/change_list_results.html b/django/contrib/admin/templates/admin/change_list_results.html index b1db6470c9..e3d4b2549a 100644 --- a/django/contrib/admin/templates/admin/change_list_results.html +++ b/django/contrib/admin/templates/admin/change_list_results.html @@ -11,15 +11,17 @@ {% for header in result_headers %} - {% if header.sortable %}{% endif %} - {{ header.text|capfirst }} - {% if header.sortable %} - {% if header.sort_pos > 0 %} - {% if header.sort_pos == 1 %} {% endif %} - {{ header.sort_pos }} - {% endif %} - - {% endif %} + {% if header.sortable %} + {% if header.sort_priority > 0 %} +
+ + {% if num_sorted_fields > 1 %}{{ header.sort_priority }}{% endif %} + +
+ {% endif %} + {% endif %} +
{% if header.sortable %}{{ header.text|capfirst }}{% else %}{{ header.text|capfirst }}{% endif %}
+
{% endfor %} @@ -33,90 +35,4 @@ - -{# Sorting popup: #} -
- - - - {% for header in result_headers|dictsort:"sort_pos" %} - {% if header.sort_pos > 0 %} - - - - - - - - {% endif %} - {% endfor %} - -
- {% trans "Sorting by:" %} -
{{ header.sort_pos }}{{ header.text|capfirst }}{% if header.ascending %}{% trans "ascending" %}{% else %}{% trans "descending" %}{% endif %}{% trans "toggle" %}{% trans "remove" %}
- - -
- - {% endif %} diff --git a/django/contrib/admin/templatetags/admin_list.py b/django/contrib/admin/templatetags/admin_list.py index 0f5eafc24d..ba3d1329ad 100644 --- a/django/contrib/admin/templatetags/admin_list.py +++ b/django/contrib/admin/templatetags/admin_list.py @@ -83,7 +83,6 @@ def result_headers(cl): """ ordering_field_columns = cl.get_ordering_field_columns() for i, field_name in enumerate(cl.list_display): - admin_order_field = None text, attr = label_for_field(field_name, cl.model, model_admin = cl.model_admin, return_attr = True @@ -95,25 +94,31 @@ def result_headers(cl): if field_name == 'action_checkbox': yield { "text": text, - "class_attrib": mark_safe(' class="action-checkbox-column"') + "class_attrib": mark_safe(' class="action-checkbox-column"'), + "sortable": False, } continue admin_order_field = getattr(attr, "admin_order_field", None) if not admin_order_field: # Not sortable - yield {"text": text} + yield { + "text": text, + "sortable": False, + } continue # OK, it is sortable if we got this far - th_classes = [] + th_classes = ['sortable'] order_type = '' new_order_type = 'asc' - sort_pos = 0 + sort_priority = 0 + sorted = False # Is it currently being sorted on? if i in ordering_field_columns: + sorted = True order_type = ordering_field_columns.get(i).lower() - sort_pos = ordering_field_columns.keys().index(i) + 1 + sort_priority = ordering_field_columns.keys().index(i) + 1 th_classes.append('sorted %sending' % order_type) new_order_type = {'asc': 'desc', 'desc': 'asc'}[order_type] @@ -144,8 +149,9 @@ def result_headers(cl): yield { "text": text, "sortable": True, + "sorted": sorted, "ascending": order_type == "asc", - "sort_pos": sort_pos, + "sort_priority": sort_priority, "url_primary": cl.get_query_string({ORDER_VAR: '.'.join(o_list_primary)}), "url_remove": cl.get_query_string({ORDER_VAR: '.'.join(o_list_remove)}), "url_toggle": cl.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}), @@ -260,13 +266,14 @@ def result_list(cl): Displays the headers and data list together """ headers = list(result_headers(cl)) + num_sorted_fields = 0 for h in headers: - # Sorting in templates depends on sort_pos attribute - h.setdefault('sort_pos', 0) + if h['sortable'] and h['sorted']: + num_sorted_fields += 1 return {'cl': cl, 'result_hidden_fields': list(result_hidden_fields(cl)), 'result_headers': headers, - 'reset_sorting_url': cl.get_query_string(remove=[ORDER_VAR]), + 'num_sorted_fields': num_sorted_fields, 'results': list(results(cl))} @register.inclusion_tag('admin/date_hierarchy.html') diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 5b92f95f59..9cf268a869 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -360,13 +360,16 @@ Removed admin icons ~~~~~~~~~~~~~~~~~~~ As part of an effort to improve the performance and usability of the admin's -vertical and horizontal "filter" widgets, some icon files were removed and -grouped into a single sprite file (``selector-icons.gif``): +changelist sorting interface and of the admin's :attr:`horizontal +` and :attr:`vertical +` "filter" widgets, some icon +files were removed and grouped into two sprite files, respectively: ``selector-add.gif``, ``selector-addall.gif``, ``selector-remove.gif``, ``selector-removeall.gif``, ``selector_stacked-add.gif`` and -``selector_stacked-remove.gif``. If you used those icons to customize the -admin then you will want to replace them with your own icons or retrieve them -from a previous release. +``selector_stacked-remove.gif`` into ``selector-icons.gif``; and +``arrow-up.gif`` and ``arrow-down.gif`` into ``sorting-icons.gif``. If you used +those icons to customize the admin then you will want to replace them with your +own icons or retrieve them from a previous release. Compatibility with old signed data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.3