Repository: OCHA-DAP/hdx-ckan

Issue:
Search Results: changes to indicator and dataset snippet
1. Remove `Download` from **indicators**.  `Preview` remains.  `Follow this Indicator` remains (and is only visible to authenticated users.
2. Remove `Preview | Download` from **datasets**. `Follow this dataset` remains (and is only visible to authenticated users.

Indicator Page (Amok) v2: Left panel - Ajax calls
Annotated mockup:
https://docs.google.com/drawings/d/1Lz6WMWDLEbeEHW1Uh7MQ-J2VbiJAvYPCL0JKb73qKzg/edit
The left panel will have to display different the sorting orders:
- Values desc (default)
- Values asc
- Alphabet (A-Z)
- Alphabet (Z-A)
  The main target for this issues is:
  The values can be retrieved by Ajax call immediately after the graph first time loads
- screenshot attached
  ![locations-sortorder](https://cloud.githubusercontent.com/assets/3865844/4456598/4abb585a-488c-11e4-9b3e-b38b3d43691d.png)



Discussion:

- the problem is that now we are altering 2 paramenters in the data retrieved from the CPS API: period and sorting 
- we can't solve this issue without caching 4 sort types X 11 period types = 44 sets of data - which is a bit too much and a lot of queries would be generated 
- talked with Dan and we are not implementing this right now - instead we'll add a loading icon on the graph when the data is reloaded from the server

pinging @cjhendrix 

Good call.  That seems like a good place to start. 


Resolving patch:
diff --git a/ckanext-hdx_theme/ckanext/hdx_theme/helpers/helpers.py b/ckanext-hdx_theme/ckanext/hdx_theme/helpers/helpers.py
--- a/ckanext-hdx_theme/ckanext/hdx_theme/helpers/helpers.py
+++ b/ckanext-hdx_theme/ckanext/hdx_theme/helpers/helpers.py
@@ -1,7 +1,7 @@
 from ckan.controllers import group
 import ckan.lib.helpers as h
 from ckan.common import (
-     c, request
+    c, request
 )
 import sqlalchemy
 import ckan.model as model
@@ -28,7 +28,7 @@
 downloadable_formats = {
     'csv', 'xls', 'xlsx', 'txt', 'jpg', 'jpeg', 'png', 'gif', 'zip', 'xml'
 }
-                    
+
 
 def is_downloadable(resource):
     format = resource.get('format', 'data').lower()
@@ -36,131 +36,152 @@ def is_downloadable(resource):
         return True
     return False
 
+
 def get_facet_items_dict(facet, limit=1000, exclude_active=False):
-    facets = h.get_facet_items_dict(facet, limit, exclude_active=exclude_active)
+    facets = h.get_facet_items_dict(
+        facet, limit, exclude_active=exclude_active)
     filtered_no_items = c.search_facets.get(facet)['items'].__len__()
-    total_no_items=json.loads(count.CountController.list[facet](count.CountController()))['count']
+    total_no_items = json.loads(
+        count.CountController.list[facet](count.CountController()))['count']
     if filtered_no_items < 50 and filtered_no_items < total_no_items:
-        no_items=filtered_no_items
+        no_items = filtered_no_items
     else:
-        no_items=total_no_items
+        no_items = total_no_items
 
     if c.search_facets_limits:
         limit = c.search_facets_limits.get(facet)
     if limit:
-        return (facets[:limit],no_items)
+        return (facets[:limit], no_items)
     else:
-        return (facets,no_items)
-    
+        return (facets, no_items)
+
+
 def get_last_modifier_user(rev_id, get_timestamp=False):
-    act_list = model.Session.query(model.Activity).filter(model.Activity.revision_id == rev_id).all()
-    if act_list and len(act_list)>0:
+    act_list = model.Session.query(model.Activity).filter(
+        model.Activity.revision_id == rev_id).all()
+    if act_list and len(act_list) > 0:
         act = act_list[0]
         usr_id = act.user_id
         if get_timestamp:
             return (model.User.get(usr_id), act.timestamp.isoformat())
         return model.User.get(usr_id)
-    #in case there is no update date it will be displayed the current date
-    usr_list = model.Session.query(model.User).filter(model.User.name == 'hdx').all()
+    # in case there is no update date it will be displayed the current date
+    usr_list = model.Session.query(model.User).filter(
+        model.User.name == 'hdx').all()
     usr = usr_list[0]
     return (usr.id, datetime.datetime.now().isoformat())
 
+
 def get_filtered_params_list(params):
     result = []
     for (key, value) in params.items():
-        if key not in {'q','sort'} :
-            result.append((key,value))
-    return result;
+        if key not in {'q', 'sort'}:
+            result.append((key, value))
+    return result
+
 
 def get_last_revision_package(package_id):
-#     pkg_list  = model.Session.query(model.Package).filter(model.Package.id == package_id).all()
-#     pkg = pkg_list[0]
-#     return pkg.latest_related_revision.id
-    activity_objects = model.activity.package_activity_list(package_id, limit=1, offset=0)
-    if len(activity_objects)>0 :
+    #     pkg_list  = model.Session.query(model.Package).filter(model.Package.id == package_id).all()
+    #     pkg = pkg_list[0]
+    #     return pkg.latest_related_revision.id
+    activity_objects = model.activity.package_activity_list(
+        package_id, limit=1, offset=0)
+    if len(activity_objects) > 0:
         activity = activity_objects[0]
         return activity.revision_id
     return None
 
 
 def get_last_revision_group(group_id):
-#     grp_list  = model.Session.query(model.Group).filter(model.Group.id == group_id).all()
-#     grp = grp_list[0]
-#     last_rev = grp.all_related_revisions[0][0]
-    activity_objects = model.activity.group_activity_list(group_id, limit=1, offset=0)
-    if len(activity_objects)>0 :
+    #     grp_list  = model.Session.query(model.Group).filter(model.Group.id == group_id).all()
+    #     grp = grp_list[0]
+    #     last_rev = grp.all_related_revisions[0][0]
+    activity_objects = model.activity.group_activity_list(
+        group_id, limit=1, offset=0)
+    if len(activity_objects) > 0:
         activity = activity_objects[0]
         return activity.revision_id
     return None
 
+
 def get_last_revision_timestamp_group(group_id):
-    activity_objects = model.activity.group_activity_list(group_id, limit=1, offset=0)
-    if len(activity_objects)>0 :
+    activity_objects = model.activity.group_activity_list(
+        group_id, limit=1, offset=0)
+    if len(activity_objects) > 0:
         activity = activity_objects[0]
         return h.render_datetime(activity.timestamp)
     return None
 
+
 def get_group_followers(grp_id):
     result = logic.get_action('group_follower_count')(
-            {'model': model, 'session': model.Session},
-            {'id': grp_id})
+        {'model': model, 'session': model.Session},
+        {'id': grp_id})
     return result
 
+
 def get_group_members(grp_id):
     member_list = logic.get_action('member_list')(
-            {'model': model, 'session': model.Session},
-            {'id': grp_id, 'object_type': 'user'})
+        {'model': model, 'session': model.Session},
+        {'id': grp_id, 'object_type': 'user'})
     result = len(member_list)
     return result
 
+
 def hdx_get_user_info(user_id):
     context = {'model': model, 'session': model.Session,
-                   'user': c.user or c.author}
+               'user': c.user or c.author}
     try:
-        user    = tk.get_action('hdx_basic_user_info')(context,{'id':user_id})
+        user = tk.get_action('hdx_basic_user_info')(context, {'id': user_id})
     except logic.NotAuthorized:
-            base.abort(401, _('Unauthorized to see organization member list'))    
-        
+        base.abort(401, _('Unauthorized to see organization member list'))
+
     return user
 
+
 def markdown_extract_strip(text, extract_length=190):
     ''' return the plain text representation of markdown encoded text.  That
     is the texted without any html tags.  If extract_length is 0 then it
     will not be truncated.'''
     result_text = h.markdown_extract(text, extract_length)
-    result = result_text.rstrip('\n').replace('\n', ' ').replace('\r', '').replace('"',"&quot;")
+    result = result_text.rstrip('\n').replace(
+        '\n', ' ').replace('\r', '').replace('"', "&quot;")
     return result
 
+
 def render_date_from_concat_str(str, separator='-'):
-    result  = ''
+    result = ''
     if str:
-        strdate_list    = str.split(separator)
-        for index,strdate in enumerate(strdate_list):
+        strdate_list = str.split(separator)
+        for index, strdate in enumerate(strdate_list):
             try:
                 date = datetime.datetime.strptime(strdate.strip(), '%m/%d/%Y')
-                render_strdate  = date.strftime('%b %d, %Y');
-                result  += render_strdate
-                if index < len(strdate_list)-1:
+                render_strdate = date.strftime('%b %d, %Y')
+                result += render_strdate
+                if index < len(strdate_list) - 1:
                     result += ' - '
             except ValueError, e:
                 log.warning(e)
-    
+
     return result
 
+
 def hdx_build_nav_icon_with_message(menu_item, title, **kw):
-    htmlResult  = h.build_nav_icon(menu_item, title, **kw)
+    htmlResult = h.build_nav_icon(menu_item, title, **kw)
     if 'message' not in kw or not kw['message']:
         return htmlResult
     else:
-        newResult   = str(htmlResult).replace('</a>', 
-                    ' <span class="nav-short-message">{message}</span></a>'.format(message=kw['message']) )
+        newResult = str(htmlResult).replace('</a>',
+                                            ' <span class="nav-short-message">{message}</span></a>'.format(message=kw['message']))
         return h.literal(newResult)
-    
+
+
 def hdx_linked_user(user, maxlength=0):
     response = h.linked_user(user, maxlength)
-    changed_response = re.sub(r"<img[^>]+/>","", response)
+    changed_response = re.sub(r"<img[^>]+/>", "", response)
     return h.literal(changed_response)
 
+
 def hdx_show_singular_plural(num, singular_word, plural_word, show_number=True):
     response = None
     if num == 1:
@@ -173,41 +194,47 @@ def hdx_show_singular_plural(num, singular_word, plural_word, show_number=True):
     else:
         return response
 
+
 def hdx_num_of_new_related_items():
-    max_days = 30;
-    count = 0;
+    max_days = 30
+    count = 0
     now = datetime.datetime.now()
     for related in c.pkg.related:
         if (related.created):
-            difference  = now-related.created
+            difference = now - related.created
             days = difference.days
             if days < max_days:
                 count += 1
     return count
 
+
 def hdx_member_roles_list():
     context = {'model': model, 'session': model.Session,
-                   'user': c.user or c.author}
+               'user': c.user or c.author}
     return tk.get_action('member_roles_list')(context, {})
 
+
 def hdx_version():
     return version.hdx_version
 
-def hdx_get_extras_element(extras, key='key', value_key='org_url', ret_key='value' ):
+
+def hdx_get_extras_element(extras, key='key', value_key='org_url', ret_key='value'):
     res = ''
-    for ex in extras :
+    for ex in extras:
         if ex[key] == value_key:
             res = ex[ret_key]
     return res
 
+
 def hdx_group_followee_list():
 
     context = {'model': model, 'session': model.Session,
                'user': c.user or c.author, 'auth_user_obj': c.userobj,
                'for_view': True}
 
-    list = logic.get_action('group_followee_list')(context, {'id': c.userobj.id})
-    #filter out the orgs
+    list = logic.get_action('group_followee_list')(
+        context, {'id': c.userobj.id})
+    # filter out the orgs
     groups = [group for group in list if not group['is_organization']]
 
     return groups
@@ -220,8 +247,10 @@ def hdx_organizations_available_with_roles():
         orgs_where_admin = []
     am_sysadmin = new_authz.is_sysadmin(c.user)
     if not am_sysadmin:
-        orgs_where_editor = set([org['id'] for org in h.organizations_available('create_dataset')])
-        orgs_where_admin = set([org['id'] for org in h.organizations_available('admin')])
+        orgs_where_editor = set(
+            [org['id'] for org in h.organizations_available('create_dataset')])
+        orgs_where_admin = set([org['id']
+                                for org in h.organizations_available('admin')])
 
     for org in organizations_available:
         org['has_add_dataset_rights'] = True
@@ -236,9 +265,10 @@ def hdx_organizations_available_with_roles():
             org['has_add_dataset_rights'] = False
 
     organizations_available.sort(key=lambda y:
-                                y['display_name'].lower())
+                                 y['display_name'].lower())
     return organizations_available
 
+
 def hdx_remove_schema_and_domain_from_url(url):
     urlTuple = urlparse.urlparse(url)
     if url.endswith('/preview'):
@@ -248,7 +278,7 @@ def hdx_remove_schema_and_domain_from_url(url):
         modifiedTuple = (('', '') + urlTuple[2:6])
     else:
         # this is for txt files
-        # we force https since otherwise the browser will 
+        # we force https since otherwise the browser will
         # anyway block loading mixed active content
         modifiedTuple = (('',) + urlTuple[1:6])
     modifiedUrl = urlparse.urlunparse(modifiedTuple)
@@ -258,13 +288,15 @@ def hdx_remove_schema_and_domain_from_url(url):
 def hdx_get_ckan_config(config_name):
     return config.get(config_name)
 
+
 def get_group_name_from_list(glist, gid):
     for group in glist:
         if group['id'] == gid:
             return group['title']
     return ""
 
-def hdx_follow_link(obj_type, obj_id, extra_text):
+
+def hdx_follow_link(obj_type, obj_id, extra_text, cls=None):
     obj_type = obj_type.lower()
     assert obj_type in h._follow_objects
     # If the user is logged in show the follow/unfollow button
@@ -273,12 +305,14 @@ def hdx_follow_link(obj_type, obj_id, extra_text):
         action = 'am_following_%s' % obj_type
         following = logic.get_action(action)(context, {'id': obj_id})
         return h.snippet('search/snippets/follow_link.html',
-                       following=following,
-                       obj_id=obj_id,
-                       obj_type=obj_type,
-                       extra_text=extra_text)
+                         following=following,
+                         obj_id=obj_id,
+                         obj_type=obj_type,
+                         extra_text=extra_text,
+                         cls=cls)
     return ''
 
+
 def follow_status(obj_type, obj_id):
     obj_type = obj_type.lower()
     assert obj_type in h._follow_objects
@@ -290,12 +324,14 @@ def follow_status(obj_type, obj_id):
         return following
     return False
 
+
 def one_active_item(items):
     for i in items:
         if i['active']:
             return True
     return False
 
+
 def feature_count(features):
     count = 0
     for name in features:
@@ -304,10 +340,11 @@ def feature_count(features):
             count += f['count']
     return count
 
+
 def hdx_follow_button(obj_type, obj_id, **kw):
     ''' This is a modified version of the ckan core follow_button() helper
     It returns a simple link for a bootstrap dropdown menu
-    
+
     Return a follow button for the given object type and id.
 
     If the user is not logged in return an empty string instead.
@@ -331,8 +368,8 @@ def hdx_follow_button(obj_type, obj_id, **kw):
         action = 'am_following_%s' % obj_type
         following = logic.get_action(action)(context, {'id': obj_id})
         return h.snippet('snippets/hdx_follow_button.html',
-                       following=following,
-                       obj_id=obj_id,
-                       obj_type=obj_type,
-                       params = kw)
+                         following=following,
+                         obj_id=obj_id,
+                         obj_type=obj_type,
+                         params=kw)
     return ''


Test patch: