[ckan-changes] [okfn/ckan] e7db2c: [1821] Alter facet_sidebar helper function to use ...

GitHub noreply at github.com
Tue Apr 17 16:14:45 UTC 2012


  Branch: refs/heads/feature-1821-multilingual-extension
  Home:   https://github.com/okfn/ckan
  Commit: e7db2cd8c1934df7432d9b49b3af94151a7091ee
      https://github.com/okfn/ckan/commit/e7db2cd8c1934df7432d9b49b3af94151a7091ee
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/templates/facets.html

  Log Message:
  -----------
  [1821] Alter facet_sidebar helper function to use the new facet data structure


diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html
index 9e135e7..05bb367 100644
--- a/ckan/templates/facets.html
+++ b/ckan/templates/facets.html
@@ -21,17 +21,17 @@
 </py:def>
 
 <py:def function="facet_sidebar(code, limit=5, label=lambda n: n, title=h.facet_title, if_empty=None, count_label=lambda c: ' (%d)'%c)">
-    <div py:if="if_empty is not None or len(h.facet_items(code, limit=limit))" class="facet-box">
+    <div py:if="if_empty is not None or c.new_facets[code]['items'][:limit]" class="facet-box">
         <h2>${title(code)}</h2>
         <ul class="facet-options">
-            <li py:for="name, count in h.facet_items(code, limit=limit)"
-                py:if="not (code, name) in c.fields">
-                  <a href="${c.drill_down_url(**{code: name})}">
-                  <span py:if="'format' in code.lower()">${h.icon(h.format_icon(name))}</span>
-                    ${label(name)}</a>${count_label(count)}
+            <li py:for="facet_item in c.new_facets[code]['items'][:limit]"
+                py:if="not (code, facet_item.name) in c.fields">
+                  <a href="${c.drill_down_url(**{code: facet_item.name})}">
+                  <span py:if="'format' in code.lower()">${h.icon(h.format_icon(facet_item.name))}</span>
+                    ${label(facet_item.name)}</a>${count_label(facet_item['count'])}
             </li>
         </ul>
-        <p py:if="not len(h.facet_items(code, limit=limit))">${if_empty}</p>
+        <p py:if="not c.new_facets[code]['items'][:limit]">${if_empty}</p>
     </div>
 </py:def>
 
@@ -46,10 +46,10 @@
         If if_empty is not None and there are no facets to filter on, then a
         single <li> element is generated, with the text specified by if_empty
         -->
-        <li py:if="if_empty and len(h.facet_items(code, limit=limit)) == 0">${if_empty}</li>
-        <li py:for="name, count in h.facet_items(code, limit=limit)"
-            py:if="not (code, name) in c.fields">
-            <a href="${c.drill_down_url(**{code: name})}">${label(name)}</a> (${count})
+        <li py:if="if_empty and not c.new_facets[code]['items']">${if_empty}</li>
+        <li py:for="facet_item in c.new_facets[code]['items'][:limit]"
+            py:if="not (code, facet_item.name) in c.fields">
+            <a href="${c.drill_down_url(**{code: facet_item.name})}">${label(facet_item.name)}</a> (facet_item['count'])
         </li>
 </py:def>
 


================================================================
  Commit: cdc1e9a87c6c3e2afed6fd8ed679860432230e64
      https://github.com/okfn/ckan/commit/cdc1e9a87c6c3e2afed6fd8ed679860432230e64
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/templates/facets.html

  Log Message:
  -----------
  [1821] Generalize facet_div helper function

Although not precisely backward-compatible with the existing
`facet_sidebar` function, this commit provides the same functionality to
the `facet_div` function.  The function parameters aren't identical though,
hence it's not backward incompatible.

I think this is a slightly cleaner interface than the existing
`facet_sidebar` function, hence not providing a drop-in replacement for
`facet_sidebar`."


diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html
index 05bb367..d7935e0 100644
--- a/ckan/templates/facets.html
+++ b/ckan/templates/facets.html
@@ -5,18 +5,44 @@
   py:strip=""
   >
 
-<py:def function="facet_div(name, title, limit=5)">
-    <div py:if="c.new_facets[name]['items'][:limit]" class="facet-box">
+<!--
+Construct a facet <div> populated with links to filtered results.
+
+name
+  The field name identifying the facet field, eg. "tags"
+
+title
+  The title of the facet, eg. "Tags", or "Tag Cloud"
+
+label_function
+  Renders the human-readable label for each facet value.
+  If defined, this should be a callable that accepts a `facet_item`.
+  eg. lambda facet_item: facet_item.display_name.upper()
+  By default it displays the facet item's display name, which should
+  usually be good enough
+
+if_empty
+  A string, which if defined, and the list of possible facet items is empty,
+  is displayed in lieu of an empty list.
+
+count_label
+  A callable which accepts an integer, and returns a string.  This controls
+  how a facet-item's count is displayed.
+  
+-->
+<py:def function="facet_div(name, title, limit=5, label_function=lambda item: item.display_name, if_empty=None, count_label=lambda c: ' (%d)'%c)">
+    <div py:if="if_empty is not None or c.new_facets[name]['items'][:limit]" class="facet-box">
         <h2>${h.facet_title(title)}</h2>
         <ul class="facet-options">
             <li py:for="facet_item in c.new_facets[name]['items'][:limit]"
                 py:if="not (name, facet_item.name) in c.fields">
                 <a href="${c.drill_down_url(**{name: facet_item.name})}">
-                    ${facet_item.display_name}
+                    ${label_function(facet_item)}
                 </a>
-                (${facet_item['count']})
+                ${count_label(facet_item['count'])}
             </li>
         </ul>
+        <p py:if="not c.new_facets[name]['items'][:limit]">${if_empty}</p>
     </div>
 </py:def>
 


================================================================
  Commit: ab83b53b1e11a3f7a44416bacb9c1f16babb722e
      https://github.com/okfn/ckan/commit/ab83b53b1e11a3f7a44416bacb9c1f16babb722e
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/templates/facets.html

  Log Message:
  -----------
  [1821] Deprecated the facet_sidebar helper function.


diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html
index d7935e0..64277ef 100644
--- a/ckan/templates/facets.html
+++ b/ckan/templates/facets.html
@@ -46,7 +46,46 @@
     </div>
 </py:def>
 
+<!--
+DEPRECATED.  Provided only for backward compatibility with existing plugins.
+
+Similar to the above, `facet_div` function; this helper creates a <div>
+populated with links to filtered search results.
+
+Differences with the preferred `facet_div` function:
+
+ * `title` argument is a callable
+ * `label` is a callable that accepts a string cf. `label_function` which is
+   a callable that accepts a `facet_item`.
+
+code
+  The field name identifying the facet field, eg. "tags"
+
+title
+  A callable used to render the title for the facet.  The callable must accept
+  one string argument, the `code` argument passed in above.  Obviously, this
+  is a bit redundant.
+
+label
+  Renders the human-readable label for each facet value.
+  If defined, this should be a callable that accepts a facet_item's name as a
+  string.
+
+if_empty
+  A string, which if defined, and the list of possible facet items is empty,
+  is displayed in lieu of an empty list.
+
+count_label
+  A callable which accepts an integer, and returns a string.  This controls
+  how a facet-item's count is displayed.
+  
+-->
 <py:def function="facet_sidebar(code, limit=5, label=lambda n: n, title=h.facet_title, if_empty=None, count_label=lambda c: ' (%d)'%c)">
+    <?python
+      import logging
+      log = logging.getLogger('ckan.templates.facets')
+      log.warning("Deprecated function: ckan/templates/facets.html:facet_sidebar()")
+    ?>
     <div py:if="if_empty is not None or c.new_facets[code]['items'][:limit]" class="facet-box">
         <h2>${title(code)}</h2>
         <ul class="facet-options">


================================================================
  Commit: 7f3c6540cf7c424a9205001837cd85a4741ab37d
      https://github.com/okfn/ckan/commit/7f3c6540cf7c424a9205001837cd85a4741ab37d
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/templates/facets.html

  Log Message:
  -----------
  [1821] Added some documentation to the facet_list_items() helper function.


diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html
index 64277ef..bd25dc6 100644
--- a/ckan/templates/facets.html
+++ b/ckan/templates/facets.html
@@ -100,17 +100,27 @@
     </div>
 </py:def>
 
-<py:def function="facet_list_items(code, limit=5, label=lambda n: n, if_empty=None)">
-        <!-- Creates a possibly empty list of <li> elements containing links to
-        further search results
+<!--
+Construct a possibly empty list of <li> elements containing links to further
+search results
 
-        This is different from facet_sidebar() (above) in that it requires the
-        caller to wrap up the resulting <li> elements in whatever dom element
-        they need.  But it does allow for filters to displayed in a hierarchy.
+This is different from `facet_sidebar` and `facet_div` (above) in that it
+requires the caller to wrap up the resulting <li> elements in whatever dom
+element they need.  But it *does* allow for filters to displayed in a
+hierarchy.
 
-        If if_empty is not None and there are no facets to filter on, then a
-        single <li> element is generated, with the text specified by if_empty
-        -->
+label
+  Renders the human-readable label for each facet value.
+  If defined, this should be a callable that accepts a facet_item's name as a
+  string.
+
+if_empty
+  If if_empty is not None and there are no facets to filter on, then a single
+  <li> element is generated, with the text specified by if_empty
+
+-->
+<py:def function="facet_list_items(code, limit=5, label=lambda n: n, if_empty=None)">
+        
         <li py:if="if_empty and not c.new_facets[code]['items']">${if_empty}</li>
         <li py:for="facet_item in c.new_facets[code]['items'][:limit]"
             py:if="not (code, facet_item.name) in c.fields">


================================================================
  Commit: 80d765e0d5cf8ee6300dd0f6d06ca0eb78131a95
      https://github.com/okfn/ckan/commit/80d765e0d5cf8ee6300dd0f6d06ca0eb78131a95
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/lib/helpers.py
    M ckan/lib/helpers_clean.py
    M ckan/templates/facets.html

  Log Message:
  -----------
  [1821] Fix bug in new_facet facet helper functions.

The new_facet wasn't taking into consideration the current request's
parameters when limiting the facets to display.  This meant that the
filter list on the right hand side of the search page could be empty for
a given facet, even if there were further filters to apply.

 * I'm not sure helpers.py is the best way of achieving this.  It's
   parallel to how the old facets work though.


diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py
index 7996e7f..1dba4ea 100644
--- a/ckan/lib/helpers.py
+++ b/ckan/lib/helpers.py
@@ -334,6 +334,18 @@ def _subnav_named_route(text, routename, **kwargs):
 def default_group_type():
     return str( config.get('ckan.default.group_type', 'group') )
 
+def new_facet_items(name, limit=10):
+    if not c.new_facets or \
+       not c.new_facets.get(name) or \
+       not c.new_facets.get(name).get('items'):
+        return []
+    facets = []
+    for facet_item in c.new_facets.get(name)['items']:
+        if not len(facet_item['name'].strip()):
+            continue
+        if not (name, facet_item['name']) in request.params.items():
+            facets.append(facet_item)
+    return sorted(facets, key=lambda item: item['count'], reverse=True)[:limit]
 
 def facet_items(*args, **kwargs):
     # facet_items() used to need c passing as the first arg
diff --git a/ckan/lib/helpers_clean.py b/ckan/lib/helpers_clean.py
index 54c50c8..cc42060 100644
--- a/ckan/lib/helpers_clean.py
+++ b/ckan/lib/helpers_clean.py
@@ -28,6 +28,7 @@
            subnav_link,
            subnav_named_route,
            default_group_type,
+           new_facet_items,
            facet_items,
            facet_title,
          #  am_authorized, # depreciated
diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html
index bd25dc6..744c947 100644
--- a/ckan/templates/facets.html
+++ b/ckan/templates/facets.html
@@ -31,10 +31,10 @@
   
 -->
 <py:def function="facet_div(name, title, limit=5, label_function=lambda item: item.display_name, if_empty=None, count_label=lambda c: ' (%d)'%c)">
-    <div py:if="if_empty is not None or c.new_facets[name]['items'][:limit]" class="facet-box">
+    <div py:if="if_empty is not None or h.new_facet_items(name, limit)" class="facet-box">
         <h2>${h.facet_title(title)}</h2>
         <ul class="facet-options">
-            <li py:for="facet_item in c.new_facets[name]['items'][:limit]"
+            <li py:for="facet_item in h.new_facet_items(name, limit)"
                 py:if="not (name, facet_item.name) in c.fields">
                 <a href="${c.drill_down_url(**{name: facet_item.name})}">
                     ${label_function(facet_item)}
@@ -42,7 +42,7 @@
                 ${count_label(facet_item['count'])}
             </li>
         </ul>
-        <p py:if="not c.new_facets[name]['items'][:limit]">${if_empty}</p>
+        <p py:if="not h.new_facet_items(name, limit)">${if_empty}</p>
     </div>
 </py:def>
 
@@ -86,17 +86,17 @@
       log = logging.getLogger('ckan.templates.facets')
       log.warning("Deprecated function: ckan/templates/facets.html:facet_sidebar()")
     ?>
-    <div py:if="if_empty is not None or c.new_facets[code]['items'][:limit]" class="facet-box">
+    <div py:if="if_empty is not None or h.new_facet_items(code, limit)" class="facet-box">
         <h2>${title(code)}</h2>
         <ul class="facet-options">
-            <li py:for="facet_item in c.new_facets[code]['items'][:limit]"
+            <li py:for="facet_item in h.new_facet_items(code, limit)"
                 py:if="not (code, facet_item.name) in c.fields">
                   <a href="${c.drill_down_url(**{code: facet_item.name})}">
                   <span py:if="'format' in code.lower()">${h.icon(h.format_icon(facet_item.name))}</span>
                     ${label(facet_item.name)}</a>${count_label(facet_item['count'])}
             </li>
         </ul>
-        <p py:if="not c.new_facets[code]['items'][:limit]">${if_empty}</p>
+        <p py:if="not h.new_facet_items(code, limit)">${if_empty}</p>
     </div>
 </py:def>
 
@@ -121,8 +121,8 @@
 -->
 <py:def function="facet_list_items(code, limit=5, label=lambda n: n, if_empty=None)">
         
-        <li py:if="if_empty and not c.new_facets[code]['items']">${if_empty}</li>
-        <li py:for="facet_item in c.new_facets[code]['items'][:limit]"
+        <li py:if="if_empty and not h.new_facet_items(code, limit)">${if_empty}</li>
+        <li py:for="facet_item in h.new_facet_items(code, limit)"
             py:if="not (code, facet_item.name) in c.fields">
             <a href="${c.drill_down_url(**{code: facet_item.name})}">${label(facet_item.name)}</a> (facet_item['count'])
         </li>


================================================================
  Commit: dd761627705c5c77a81012b5e1c2015dece71f9e
      https://github.com/okfn/ckan/commit/dd761627705c5c77a81012b5e1c2015dece71f9e
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/lib/helpers.py
    M ckan/templates/facets.html

  Log Message:
  -----------
  [1821] Add deprecation warnings to uses of the old facets

See ticket #2313


diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py
index 1dba4ea..9c2ff6d 100644
--- a/ckan/lib/helpers.py
+++ b/ckan/lib/helpers.py
@@ -7,6 +7,7 @@
 """
 import email.utils
 import datetime
+import logging
 import re
 import urllib
 
@@ -48,6 +49,8 @@
 except ImportError:
     import simplejson as json
 
+_log = logging.getLogger(__name__)
+
 def redirect_to(*args, **kw):
     '''A routes.redirect_to wrapper to retain the i18n settings'''
     kw['__ckan_no_root'] = True
@@ -348,6 +351,10 @@ def new_facet_items(name, limit=10):
     return sorted(facets, key=lambda item: item['count'], reverse=True)[:limit]
 
 def facet_items(*args, **kwargs):
+    """
+    DEPRECATED: Use the new facet data structure, and `new_facet_items()`
+    """
+    _log.warning('Deprecated function: ckan.lib.helpers:facet_items().  Will be removed in v1.8')
     # facet_items() used to need c passing as the first arg
     # this is depriciated as pointless
     # throws error if ckan.restrict_template_vars is True
diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html
index 744c947..05c19b5 100644
--- a/ckan/templates/facets.html
+++ b/ckan/templates/facets.html
@@ -48,6 +48,7 @@
 
 <!--
 DEPRECATED.  Provided only for backward compatibility with existing plugins.
+             Use `facet_div` instead.
 
 Similar to the above, `facet_div` function; this helper creates a <div>
 populated with links to filtered search results.
@@ -83,8 +84,7 @@
 <py:def function="facet_sidebar(code, limit=5, label=lambda n: n, title=h.facet_title, if_empty=None, count_label=lambda c: ' (%d)'%c)">
     <?python
       import logging
-      log = logging.getLogger('ckan.templates.facets')
-      log.warning("Deprecated function: ckan/templates/facets.html:facet_sidebar()")
+      logging.getLogger('ckan.templates.facets').warning("Deprecated function: ckan/templates/facets.html:facet_sidebar()")
     ?>
     <div py:if="if_empty is not None or h.new_facet_items(code, limit)" class="facet-box">
         <h2>${title(code)}</h2>


================================================================
  Commit: dabd4982502a57de9a2664140efd0b7bd9aae66f
      https://github.com/okfn/ckan/commit/dabd4982502a57de9a2664140efd0b7bd9aae66f
  Author: Ian Murray <ian.murray at okfn.org>
  Date:   2012-04-17 (Tue, 17 Apr 2012)

  Changed paths:
    M ckan/logic/schema.py
    A ckan/migration/versions/053_add_group_logo.py
    M ckan/model/group.py
    M ckan/public/css/style.css
    M ckan/templates/group/new_group_form.html
    M ckan/templates/group/read.html
    M ckan/templates/layout_base.html
    M ckan/tests/functional/test_group.py
    M ckan/tests/lib/test_dictization.py
    M ckan/tests/lib/test_dictization_schema.py
    M ckanext/organizations/templates/organization_form.html
    A ckanext/organizations/templates/organization_history.html
    M ckanext/organizations/templates/organization_read.html

  Log Message:
  -----------
  Merge remote-tracking branch 'origin/feature-1821-multilingual-extension' into feature-1821-multilingual-extension


diff --git a/ckan/logic/schema.py b/ckan/logic/schema.py
index 8199740..0d41722 100644
--- a/ckan/logic/schema.py
+++ b/ckan/logic/schema.py
@@ -180,6 +180,7 @@ def default_group_schema():
         'name': [not_empty, unicode, name_validator, group_name_validator],
         'title': [ignore_missing, unicode],
         'description': [ignore_missing, unicode],
+        'image_url': [ignore_missing, unicode],
         'type': [ignore_missing, unicode],
         'state': [ignore_not_group_admin, ignore_missing],
         'created': [ignore],
diff --git a/ckan/migration/versions/053_add_group_logo.py b/ckan/migration/versions/053_add_group_logo.py
new file mode 100644
index 0000000..7a31fb6
--- /dev/null
+++ b/ckan/migration/versions/053_add_group_logo.py
@@ -0,0 +1,12 @@
+from sqlalchemy import *
+from migrate import *
+
+def upgrade(migrate_engine):
+    migrate_engine.execute('''
+        ALTER TABLE "group"
+            ADD COLUMN image_url text;
+
+        ALTER TABLE group_revision
+            ADD COLUMN image_url text;
+    '''
+    )
diff --git a/ckan/model/group.py b/ckan/model/group.py
index b43ee10..f622a7a 100644
--- a/ckan/model/group.py
+++ b/ckan/model/group.py
@@ -31,6 +31,7 @@
     Column('title', UnicodeText),
     Column('type', UnicodeText, nullable=False),
     Column('description', UnicodeText),
+    Column('image_url', UnicodeText),
     Column('created', DateTime, default=datetime.datetime.now),
     Column('approval_status', UnicodeText, default=u"approved"),
     )
@@ -78,11 +79,12 @@ class Group(vdm.sqlalchemy.RevisionedObjectMixin,
             vdm.sqlalchemy.StatefulObjectMixin,
             DomainObject):
 
-    def __init__(self, name=u'', title=u'', description=u'',
-                 type=u'group', approval_status=u'approved' ):
+    def __init__(self, name=u'', title=u'', description=u'', image_url=u'',
+                 type=u'group', approval_status=u'approved'):
         self.name = name
         self.title = title
         self.description = description
+        self.image_url = image_url
         self.type = type
         self.approval_status= approval_status
 
diff --git a/ckan/public/css/style.css b/ckan/public/css/style.css
index 354734e..981156e 100644
--- a/ckan/public/css/style.css
+++ b/ckan/public/css/style.css
@@ -196,6 +196,11 @@ tbody tr:nth-child(odd) td, tbody tr.odd td {
   font-size: 2.2em;
   font-weight: normal;
 }
+#page-logo {
+  max-width: 36px;
+  max-height: 36px;
+  margin-right: 5px;
+}
 .hover-for-help {
   position: relative;
 }
diff --git a/ckan/templates/group/new_group_form.html b/ckan/templates/group/new_group_form.html
index ad24ea3..9abc6c1 100644
--- a/ckan/templates/group/new_group_form.html
+++ b/ckan/templates/group/new_group_form.html
@@ -1,8 +1,8 @@
-<form 
-  class="form-horizontal ${'has-errors' if errors else ''}" 
-  id="group-edit" 
-  action="" 
-  method="post" 
+<form
+  class="form-horizontal ${'has-errors' if errors else ''}"
+  id="group-edit"
+  action=""
+  method="post"
   xmlns:i18n="http://genshi.edgewall.org/i18n"
   xmlns:py="http://genshi.edgewall.org/"
   xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -43,6 +43,13 @@
       ${markdown_editor('description', data.get('description'), 'notes', _('Start with a summary sentence ...'))}
     </div>
   </div>
+  <div class="control-group">
+    <label for="name" class="control-label">Image URL:</label>
+    <div class="controls">
+      <input id="image_url" name="image_url" type="text" value="${data.get('image_url', '')}"/>
+      <p>The URL for the image that is associated with this group.</p>
+    </div>
+  </div>
   <div class="state-field control-group" py:if="c.is_sysadmin or c.auth_for_change_state">
     <label for="" class="control-label">State</label>
     <div class="controls">
@@ -53,7 +60,7 @@
     </div>
   </div>
 </fieldset>
-  
+
 <fieldset id="extras">
   <h3>Extras</h3>
   <dl>
diff --git a/ckan/templates/group/read.html b/ckan/templates/group/read.html
index f4335c9..f08cf99 100644
--- a/ckan/templates/group/read.html
+++ b/ckan/templates/group/read.html
@@ -4,8 +4,12 @@
   py:strip="">
   
   <xi:include href="../facets.html" />
-  <py:def function="page_title">${c.group_dict.display_name}</py:def>
-  <py:def function="page_heading">${c.group_dict.display_name}</py:def>
+
+  <py:def function="page_title">${c.group.display_name}</py:def>
+  <py:def function="page_heading">${c.group.display_name}</py:def>
+  <py:if test="c.group.image_url">
+    <py:def function="page_logo">${c.group.image_url}</py:def>
+  </py:if>
 
   <py:match path="primarysidebar">
   
diff --git a/ckan/templates/layout_base.html b/ckan/templates/layout_base.html
index 3b090f1..1518d72 100644
--- a/ckan/templates/layout_base.html
+++ b/ckan/templates/layout_base.html
@@ -90,7 +90,10 @@
     </py:with>
 
     <div id="main" class="container" role="main">
-      <h1 py:if="defined('page_heading')" class="page_heading">${page_heading()}</h1>
+      <h1 py:if="defined('page_heading')" class="page_heading">
+        <img py:if="defined('page_logo')" id="page-logo" src="${page_logo()}" alt="Page Logo" />
+        ${page_heading()}
+      </h1>
       <div class="row">
         <div class="span12">
           <div id="minornavigation">
diff --git a/ckan/tests/functional/test_group.py b/ckan/tests/functional/test_group.py
index 8b452a6..e71cd28 100644
--- a/ckan/tests/functional/test_group.py
+++ b/ckan/tests/functional/test_group.py
@@ -72,7 +72,7 @@ def test_mainmenu(self):
     def test_index(self):
         offset = url_for(controller='group', action='index')
         res = self.app.get(offset)
-        assert '<h1 class="page_heading">Groups' in res, res
+        assert re.search('<h1(.*)>\s*Groups', res.body)
         groupname = 'david'
         group = model.Group.by_name(unicode(groupname))
         group_title = group.title
@@ -259,6 +259,20 @@ def test_edit_plugin_hook(self):
         assert plugin.calls['edit'] == 1, plugin.calls
         plugins.unload(plugin)
 
+    def test_edit_image_url(self):
+        group = model.Group.by_name(self.groupname)
+        offset = url_for(controller='group', action='edit', id=self.groupname)
+        res = self.app.get(offset, status=200, extra_environ={'REMOTE_USER': 'russianfan'})
+
+        form = res.forms['group-edit']
+        image_url = u'http://url.to/image_url'
+        form['image_url'] = image_url
+        res = form.submit('save', status=302, extra_environ={'REMOTE_USER': 'russianfan'})
+
+        model.Session.remove()
+        group = model.Group.by_name(self.groupname)
+        assert group.image_url == image_url, group
+
     def test_edit_non_existent(self):
         name = u'group_does_not_exist'
         offset = url_for(controller='group', action='edit', id=name)
diff --git a/ckan/tests/lib/test_dictization.py b/ckan/tests/lib/test_dictization.py
index 93dc4fb..09342d2 100644
--- a/ckan/tests/lib/test_dictization.py
+++ b/ckan/tests/lib/test_dictization.py
@@ -42,19 +42,19 @@ def setup_class(cls):
             'groups': [{'description': u'These are books that David likes.',
                         'name': u'david',
                         'capacity': 'public',
+                        'image_url': u'',
                         'type': u'group',
                         'state': u'active',
                         'title': u"Dave's books",
-                        "approval_status": u"approved",
-                        'capacity': u'public'},
+                        "approval_status": u"approved"},
                        {'description': u'Roger likes these books.',
                         'name': u'roger',
                         'capacity': 'public',
+                        'image_url': u'',
                         'type': u'group',
                         'state': u'active',
                         'title': u"Roger's books",
-                        "approval_status": u"approved",
-                        'capacity': u'public'}],
+                        "approval_status": u"approved"}],
             'isopen': True,
             'license_id': u'other-open',
             'license_title': u'Other (Open)',
@@ -216,7 +216,7 @@ def test_01_dictize_main_objects_simple(self):
     def test_02_package_dictize(self):
 
         context = {"model": model,
-                 "session": model.Session}
+                   "session": model.Session}
 
         model.Session.remove()
         pkg = model.Session.query(model.Package).filter_by(name='annakarenina').first()
@@ -869,13 +869,14 @@ def test_16_group_dictized(self):
 
         group_dictized = group_dictize(group, context)
 
-        expected =  {'description': u'',
+        expected = {'description': u'',
                     'extras': [{'key': u'genre', 'state': u'active', 'value': u'"horror"'},
                                {'key': u'media', 'state': u'active', 'value': u'"dvd"'}],
                     'tags': [{'capacity': 'public', 'name': u'russian'}],
                     'groups': [{'description': u'',
                                'capacity' : 'public',
                                'display_name': u'simple',
+                               'image_url': u'',
                                'name': u'simple',
                                'packages': 0,
                                'state': u'active',
@@ -894,6 +895,7 @@ def test_16_group_dictized(self):
                               'reset_key': None}],
                     'name': u'help',
                     'display_name': u'help',
+                    'image_url': u'',
                     'packages': [{'author': None,
                                   'author_email': None,
                                   'license_id': u'other-open',
diff --git a/ckan/tests/lib/test_dictization_schema.py b/ckan/tests/lib/test_dictization_schema.py
index aea3264..ca7c018 100644
--- a/ckan/tests/lib/test_dictization_schema.py
+++ b/ckan/tests/lib/test_dictization_schema.py
@@ -152,6 +152,7 @@ def test_2_group_schema(self):
                                  'id': group.id,
                                  'name': u'david',
                                  'type': u'group',
+                                 'image_url': u'',
                                  'packages': sorted([{'id': group_pack[0].id,
                                                     'name': group_pack[0].name,
                                                     'title': group_pack[0].title},
diff --git a/ckanext/organizations/templates/organization_form.html b/ckanext/organizations/templates/organization_form.html
index 76b28c7..df0b9d7 100644
--- a/ckanext/organizations/templates/organization_form.html
+++ b/ckanext/organizations/templates/organization_form.html
@@ -42,6 +42,15 @@
       <span class="hints">You can use <a href="http://daringfireball.net/projects/markdown/syntax" target="_blank">Markdown formatting</a> here.</span>
     </div></dd>
 
+  <div class="control-group">
+    <label for="name" class="control-label">Image URL:</label>
+    <div class="controls">
+      <input id="image_url" name="image_url" type="text" value="${data.get('image_url', '')}"/>
+      <p>The URL for the image that is associated with this group.</p>
+    </div>
+  </div>
+
+
     <dt class="parent-label" py:if="c.is_superuser_or_groupadmin">
 		<label class="field_opt" for="parent">Parent Organization</label>
 	</dt>
diff --git a/ckanext/organizations/templates/organization_history.html b/ckanext/organizations/templates/organization_history.html
new file mode 100644
index 0000000..acf10d1
--- /dev/null
+++ b/ckanext/organizations/templates/organization_history.html
@@ -0,0 +1,59 @@
+<html xmlns:py="http://genshi.edgewall.org/"
+  xmlns:xi="http://www.w3.org/2001/XInclude"
+  py:strip="">
+
+  <py:def function="page_title">History: ${c.group.display_name}</py:def>
+  <py:def function="page_heading">History: ${c.group.display_name}</py:def>
+
+  <div py:match="content" class="group">
+    <h3>
+      Revisions
+      <!--p class="atom-feed-link group-history-link">
+        <a
+          href="${h.url(controller='group', action='history', id=c.group_dict['name'], format='atom', days=7)}"
+          title="${g.site_title} - Group History - ${c.group_dict['name']}"
+          >
+          Subscribe »</a>
+      </p-->
+    </h3>
+    <form id="group-revisions" action="diff" method="post"
+      xmlns:py="http://genshi.edgewall.org/"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      >
+
+      <h3 py:if="c.error" class="form-errors">
+        Error: ${c.error}
+      </h3>
+
+      <input type="hidden" name="group_name" value="${c.group_dict['name']}"/>
+
+      <table class="table table-bordered table-striped">
+        <tr>
+          <th></th><th>Revision</th><th>Timestamp</th><th>Author</th><th>Log Message</th>
+        </tr>
+        <py:for each="index, revision_dict in enumerate(c.group_revisions)">
+          <tr>
+            <td nowrap="nowrap">
+              ${h.radio("selected1", revision_dict['id'], checked=(index == 0))}
+              ${h.radio("selected2", revision_dict['id'], checked=(index == len(c.group_revisions)-1))}
+            </td>
+            <td>
+              <a href="${h.url_for(controller='revision',action='read',id=revision_dict['id'])}">${revision_dict['id']}</a>
+            </td>
+            <td>${revision_dict['timestamp']}</td>
+            <td>${h.linked_user(revision_dict['author'])}</td>
+            <td>${revision_dict['message']}</td>
+          </tr>
+        </py:for>
+      </table>
+      <input type="submit" name="diff" value="${_('Compare »')}" class="btn primary" />
+    </form>
+  </div>
+
+  <py:def function="optional_feed">
+    <link rel="alternate" type="application/atom+xml" title="Organization History"
+      href="${h.url(controller='group', action='history', id=c.group_dict['name'], format='atom', days=7)}" />
+  </py:def>
+
+  <xi:include href="organization_layout.html" />
+</html>
diff --git a/ckanext/organizations/templates/organization_read.html b/ckanext/organizations/templates/organization_read.html
index 0176952..944192e 100644
--- a/ckanext/organizations/templates/organization_read.html
+++ b/ckanext/organizations/templates/organization_read.html
@@ -6,6 +6,9 @@
   <xi:include href="facets.html" />
   <py:def function="page_title">${c.group.display_name}</py:def>
   <py:def function="page_heading">${c.group.display_name}</py:def>
+  <py:if test="c.group.image_url">
+    <py:def function="page_logo">${c.group.image_url}</py:def>
+  </py:if>
 
   <?python
     from pylons import config


================================================================
Compare: https://github.com/okfn/ckan/compare/5ff50ec...dabd498


More information about the ckan-changes mailing list