From 7b0bbff3762a95ac505aed161dc083029ba6edf1 Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Fri, 7 Jun 2013 16:50:07 -0400 Subject: [PATCH] Added Datatables.net style sorting to all lists and related lists --- ansibleworks/ui/static/css/ansible-ui.css | 20 ++++++ .../ui/static/js/helpers/related-search.js | 61 +++++++++++++++++-- ansibleworks/ui/static/js/helpers/search.js | 49 +++++++++++++-- .../ui/static/lib/ansible/form-generator.js | 18 ++++-- .../ui/static/lib/ansible/list-generator.js | 5 +- 5 files changed, 138 insertions(+), 15 deletions(-) diff --git a/ansibleworks/ui/static/css/ansible-ui.css b/ansibleworks/ui/static/css/ansible-ui.css index bc20b44ac9..253eed55eb 100644 --- a/ansibleworks/ui/static/css/ansible-ui.css +++ b/ansibleworks/ui/static/css/ansible-ui.css @@ -361,4 +361,24 @@ vertical-align: middle; width: 100px; margin: 0 10px; + } + + + /* Sort link styles */ + + .list-header:hover { + cursor: pointer; + } + + .list-header i { + margin-left: 10px; + } + + .list-header .icon-sort { + color: #ccc; + } + + .list-header .icon-sort-down, + .list-header .icon-sort-up { + color: #36454F; } \ No newline at end of file diff --git a/ansibleworks/ui/static/js/helpers/related-search.js b/ansibleworks/ui/static/js/helpers/related-search.js index 71f36d073a..26cb13739b 100644 --- a/ansibleworks/ui/static/js/helpers/related-search.js +++ b/ansibleworks/ui/static/js/helpers/related-search.js @@ -22,7 +22,7 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat var scope = params.scope; var relatedSets = params.relatedSets; var form = params.form; - + // Set default values for (var set in form.related) { if (form.related[set].type != 'tree') { @@ -33,6 +33,7 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat break; } } + scope[form.related[set].iterator + 'SortOrder'] = null; scope[form.related[set].iterator + 'SearchType'] = 'contains'; scope[form.related[set].iterator + 'SearchTypeLabel'] = 'Contains'; scope[form.related[set].iterator + 'SelectShow'] = false; @@ -57,7 +58,7 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat scope[model + 'SearchSpin'] = true; scope[model + 'Loading'] = true; - var set, url, iterator, default_order; + var set, url, iterator, sort_order; for (var key in relatedSets) { if (relatedSets[key].iterator == model) { set = key; @@ -66,23 +67,73 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat for (var fld in form.related[key].fields) { if (form.related[key].fields[fld].key) { - default_order = fld; + sort_order = fld; } } break; } } + + sort_order = (scope[model + 'SortOrder'] == null) ? sort_order : scope[model + 'SortOrder']; + if (scope[model + 'SearchValue'] != '' && scope[model + 'SearchValue'] != undefined) { scope[model + 'SearchParams'] = '?' + scope[model + 'SearchField'] + '__' + scope[model + 'SearchType'] + '=' + escape(scope[model + 'SearchValue']); - scope[model + 'SearchParams'] += (default_order) ? '&order_by=' + escape(default_order) : ''; + scope[model + 'SearchParams'] += (sort_order) ? '&order_by=' + escape(sort_order) : ''; } else { - scope[model + 'SearchParams'] = (default_order) ? '?order_by=' + escape(default_order) : ''; + scope[model + 'SearchParams'] = (sort_order) ? '?order_by=' + escape(sort_order) : ''; } url += scope[model + 'SearchParams']; url += (scope[model + 'PageSize']) ? '&page_size=' + scope[iterator + 'PageSize'] : ""; RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url }); } + + + scope.sort = function(iterator, fld) { + var sort_order; + + // reset sort icons back to 'icon-sort' on all columns + // except the one clicked + $('.' + iterator + ' .list-header').each(function(index) { + if ($(this).attr('id') != iterator + '-' + fld + '-header') { + var icon = $(this).find('i'); + icon.attr('class','icon-sort'); + } + }); + + // Toggle the icon for the clicked column + // and set the sort direction + var icon = $('#' + iterator + '-' + fld + '-header i'); + var direction = ''; + if (icon.hasClass('icon-sort')) { + icon.removeClass('icon-sort'); + icon.addClass('icon-sort-up'); + } + else if (icon.hasClass('icon-sort-up')) { + icon.removeClass('icon-sort-up'); + icon.addClass('icon-sort-down'); + direction = '-'; + } + else if (icon.hasClass('icon-sort-down')) { + icon.removeClass('icon-sort-down'); + icon.addClass('icon-sort-up'); + } + + // Set the sorder order value and call the API to refresh the list with the new order + for (var set in form.related) { + if (form.related[set].iterator == iterator) { + if (form.related[set].fields[fld].sourceModel) { + sort_order = direction + form.related[set].fields[fld].sourceModel + '__' + + form.related[set].fields[fld].sourceModel; + } + else { + sort_order = direction + fld; + } + } + } + scope[iterator + 'SortOrder'] = sort_order; + scope.search(iterator); + } } }]); diff --git a/ansibleworks/ui/static/js/helpers/search.js b/ansibleworks/ui/static/js/helpers/search.js index d07ddfab14..d701592253 100644 --- a/ansibleworks/ui/static/js/helpers/search.js +++ b/ansibleworks/ui/static/js/helpers/search.js @@ -25,17 +25,17 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) var defaultUrl = params.url; var list = params.list; var iterator = (params.iterator) ? params.iterator : list.iterator; - var default_order; + var sort_order; // Set default values for (fld in list.fields) { if (list.fields[fld].key) { if (list.fields[fld].sourceModel) { var fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; - default_order = (list.fields[fld].desc) ? '-' + fka : fka; + sort_order = (list.fields[fld].desc) ? '-' + fka : fka; } else { - default_order = (list.fields[fld].desc) ? '-' + fld : fld; + sort_order = (list.fields[fld].desc) ? '-' + fld : fld; } scope[iterator + 'SearchField'] = fld scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label; @@ -134,16 +134,55 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) list.fields[scope[iterator + 'SearchField']].searchType == 'gtzero' ) { scope[iterator + 'SearchParams'] += escape(scope[iterator + 'SearchValue']); } - scope[iterator + 'SearchParams'] += (default_order) ? '&order_by=' + escape(default_order) : ''; + scope[iterator + 'SearchParams'] += (sort_order) ? '&order_by=' + escape(sort_order) : ''; } else { scope[iterator + 'SearchParams'] = ''; - scope[iterator + 'SearchParams'] += (default_order) ? '?order_by=' + escape(default_order) : ''; + scope[iterator + 'SearchParams'] += (sort_order) ? '?order_by=' + escape(sort_order) : ''; } scope[iterator + 'Page'] = 0; url += scope[iterator + 'SearchParams']; url += (scope[iterator + 'PageSize']) ? '&page_size=' + scope[iterator + 'PageSize'] : ""; Refresh({ scope: scope, set: set, iterator: iterator, url: url }); } + + scope.sort = function(fld) { + // reset sort icons back to 'icon-sort' on all columns + // except the one clicked + $('.list-header').each(function(index) { + if ($(this).attr('id') != fld + '-header') { + var icon = $(this).find('i'); + icon.attr('class','icon-sort'); + } + }); + + // Toggle the icon for the clicked column + // and set the sort direction + var icon = $('#' + fld + '-header i'); + var direction = ''; + if (icon.hasClass('icon-sort')) { + icon.removeClass('icon-sort'); + icon.addClass('icon-sort-up'); + } + else if (icon.hasClass('icon-sort-up')) { + icon.removeClass('icon-sort-up'); + icon.addClass('icon-sort-down'); + direction = '-'; + } + else if (icon.hasClass('icon-sort-down')) { + icon.removeClass('icon-sort-down'); + icon.addClass('icon-sort-up'); + } + + // Set the sorder order value and call the API to refresh the list with the new order + if (list.fields[fld].sourceModel) { + sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; + } + else { + sort_order = direction + fld; + } + scope.search(list.iterator); + } + } }]); diff --git a/ansibleworks/ui/static/lib/ansible/form-generator.js b/ansibleworks/ui/static/lib/ansible/form-generator.js index fca5b6e148..8d59d5c0af 100644 --- a/ansibleworks/ui/static/lib/ansible/form-generator.js +++ b/ansibleworks/ui/static/lib/ansible/form-generator.js @@ -709,12 +709,17 @@ angular.module('FormGenerator', ['GeneratorHelpers']) // Start the list html += "
\n"; - html += "\n"; + html += "
\n"; html += "\n"; html += "\n"; html += "\n"; for (var fld in form.related[itm].fields) { - html += "\n"; + html += "\n"; } html += "\n"; html += "\n"; @@ -863,12 +868,17 @@ angular.module('FormGenerator', ['GeneratorHelpers']) // Start the list html += "
\n"; - html += "
#" + form.related[itm]['fields'][fld].label + "" + + form.related[itm]['fields'][fld].label; + html += "
\n"; + html += "
\n"; html += "\n"; html += "\n"; html += "\n"; for (var fld in form.related[itm].fields) { - html += "\n"; + html += "\n"; } html += "\n"; html += "\n"; diff --git a/ansibleworks/ui/static/lib/ansible/list-generator.js b/ansibleworks/ui/static/lib/ansible/list-generator.js index e48fb639d7..d6fc3f3d10 100644 --- a/ansibleworks/ui/static/lib/ansible/list-generator.js +++ b/ansibleworks/ui/static/lib/ansible/list-generator.js @@ -182,7 +182,10 @@ angular.module('ListGenerator', ['GeneratorHelpers',]) html += "\n"; } for (var fld in list.fields) { - html += "\n"; + html += "\n"; } if (options.mode == 'select') { html += "";
#" + form.related[itm]['fields'][fld].label + "" + + form.related[itm]['fields'][fld].label; + html += "
#" + list.fields[fld].label + "" + list.fields[fld].label; + html += " Select