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 += "" + form.related[itm]['fields'][fld].label + " | \n";
+ html += "\n";
}
html += " | \n";
html += "
\n";
@@ -863,12 +868,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 += "" + form.related[itm]['fields'][fld].label + " | \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 += "" + list.fields[fld].label + " | \n";
+ html += "\n";
}
if (options.mode == 'select') {
html += "Select | ";