Repository: ckan/ckan

Issue:
Organizations are sorted by name instead of title.
### CKAN Version if known (or site URL)

2.5.2
### Please describe the expected behaviour

Organizations should be sorted by title since the title is the shown value in web interfaces.
### Please describe the actual behaviour

Organizations are sorted by name by default without any selected sorting and in the sorting dropdown.
### What steps can be taken to reproduce the issue?

Create or modify organizations so that its title starts with different letter than its name. Open Organizations list and the organization is in position which does not make sense with the shown data.



Discussion:
@amercader, I can take a look at it.
@amercader , PR is ready for this issue, its quite straightforward.
Hi @amercader , can this update be backported to CKAN 2.5 and CKAN 2.6.
Sorting by title is so embarrassing for multi-byte languages. We Japanese use MB characters for title and name is alphabetic only. MB characters are sorted with its character codes that is totally not associated with semantics nor pronunciation. So we have to control display order with tweaking group and organization names. In Addition, API specification says default is "name asc". I personally think it should be returned back to "name asc". (I found this problem when updating from 2.5)

Resolving patch:
diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py
--- a/ckan/logic/action/get.py
+++ b/ckan/logic/action/get.py
@@ -251,7 +251,7 @@ def _group_or_org_list(context, data_dict, is_org=False):
             data_dict, logic.schema.default_pagination_schema(), context)
         if errors:
             raise ValidationError(errors)
-    sort = data_dict.get('sort') or 'title'
+    sort = data_dict.get('sort') or config.get('ckan.default_group_sort') or 'title'
     q = data_dict.get('q')
 
     all_fields = asbool(data_dict.get('all_fields', None))
@@ -358,7 +358,7 @@ def group_list(context, data_dict):
       ``'packages'`` (optional, default: ``'name'``) Deprecated use sort.
     :type order_by: string
     :param sort: sorting of the search results.  Optional.  Default:
-        "name asc" string of field name and sort-order. The allowed fields are
+        "title asc" string of field name and sort-order. The allowed fields are
         'name', 'package_count' and 'title'
     :type sort: string
     :param limit: the maximum number of groups returned (optional)
@@ -409,7 +409,7 @@ def organization_list(context, data_dict):
       ``'packages'`` (optional, default: ``'name'``) Deprecated use sort.
     :type order_by: string
     :param sort: sorting of the search results.  Optional.  Default:
-        "name asc" string of field name and sort-order. The allowed fields are
+        "title asc" string of field name and sort-order. The allowed fields are
         'name', 'package_count' and 'title'
     :type sort: string
     :param limit: the maximum number of organizations returned (optional)
@@ -1559,7 +1559,7 @@ def package_search(context, data_dict):
     :param fq_list: additional filter queries to apply.
     :type fq_list: list of strings
     :param sort: sorting of the search results.  Optional.  Default:
-        ``'relevance asc, metadata_modified desc'``.  As per the solr
+        ``'score desc, metadata_modified desc'``.  As per the solr
         documentation, this is a comma-separated string of field names and
         sort-orderings.
     :type sort: string
@@ -1696,7 +1696,7 @@ def package_search(context, data_dict):
     abort = data_dict.get('abort_search', False)
 
     if data_dict.get('sort') in (None, 'rank'):
-        data_dict['sort'] = 'score desc, metadata_modified desc'
+        data_dict['sort'] = config.get('ckan.search.default_package_sort') or 'score desc, metadata_modified desc'
 
     results = []
     if not abort:


Test patch:
diff --git a/ckan/tests/logic/action/test_get.py b/ckan/tests/logic/action/test_get.py
--- a/ckan/tests/logic/action/test_get.py
+++ b/ckan/tests/logic/action/test_get.py
@@ -289,6 +289,29 @@ def test_group_list_sort_by_package_count_ascending(self):
 
         assert group_list == ["bb", "aa"]
 
+    def test_group_list_sort_default(self):
+
+        factories.Group(name="zz", title="aa")
+        factories.Group(name="yy", title="bb")
+
+        group_list = helpers.call_action(
+            "group_list"
+        )
+
+        assert group_list == ['zz', 'yy']
+
+    @pytest.mark.ckan_config("ckan.default_group_sort", "name")
+    def test_group_list_sort_from_config(self):
+
+        factories.Group(name="zz", title="aa")
+        factories.Group(name="yy", title="bb")
+
+        group_list = helpers.call_action(
+            "group_list"
+        )
+
+        assert group_list == ['yy', 'zz']
+
     def eq_expected(self, expected_dict, result_dict):
         superfluous_keys = set(result_dict) - set(expected_dict)
         assert not superfluous_keys, "Did not expect key: %s" % " ".join(
@@ -1342,6 +1365,19 @@ def test_sort(self):
         result_names = [result["name"] for result in search_result["results"]]
         assert result_names == [u"test2", u"test1", u"test0"]
 
+    @pytest.mark.ckan_config("ckan.search.default_package_sort", "metadata_created asc")
+    def test_sort_default_from_config(self):
+        factories.Dataset(name="test0")
+        factories.Dataset(name="test1")
+        factories.Dataset(name="test2")
+
+        search_result = helpers.call_action(
+            "package_search"
+        )
+
+        result_names = [result["name"] for result in search_result["results"]]
+        assert result_names == [u"test0", u"test1", u"test2"]
+
     def test_package_search_on_resource_name(self):
         """
         package_search() should allow searching on resource name field.