[ckan-changes] [okfn/ckan] 0b3089: [2347] Implemented related dashboard with filter o...
GitHub
noreply at github.com
Wed May 2 11:42:51 UTC 2012
Branch: refs/heads/feature-2347-related-dashboard
Home: https://github.com/okfn/ckan
Commit: 0b30897cd28bbc62efa2d9811cb3bff8af6627ae
https://github.com/okfn/ckan/commit/0b30897cd28bbc62efa2d9811cb3bff8af6627ae
Author: Ross Jones <rossdjones at gmail.com>
Date: 2012-05-02 (Wed, 02 May 2012)
Changed paths:
M ckan/config/routing.py
M ckan/controllers/related.py
M ckan/logic/action/get.py
R ckan/templates/_snippet/add-related.html
M ckan/templates/_util.html
R ckan/templates/package/related_list.html
A ckan/templates/related/add-related.html
A ckan/templates/related/dashboard.html
A ckan/templates/related/related_list.html
Log Message:
-----------
[2347] Implemented related dashboard with filter on type and tidied up some of the related templates
diff --git a/ckan/config/routing.py b/ckan/config/routing.py
index 43fa8fd..1ad271e 100644
--- a/ckan/config/routing.py
+++ b/ckan/config/routing.py
@@ -155,6 +155,7 @@ def make_map():
with SubMapper(map, controller='related') as m:
m.connect('related_list', '/dataset/{id}/related', action='list')
m.connect('related_read', '/dataset/{id}/related/{related_id}', action='read')
+ m.connect('related_dashboard', '/apps', action='dashboard')
with SubMapper(map, controller='package') as m:
m.connect('/dataset', action='search')
diff --git a/ckan/controllers/related.py b/ckan/controllers/related.py
index 85042aa..fb6effd 100644
--- a/ckan/controllers/related.py
+++ b/ckan/controllers/related.py
@@ -4,13 +4,59 @@
import ckan.logic as logic
import ckan.lib.base as base
import ckan.lib.helpers as h
+import urllib
c = base.c
class RelatedController(base.BaseController):
- def list(self, id):
+ def dashboard(self):
+ """ List all related items regardless of dataset """
+ context = {'model': model, 'session': model.Session,
+ 'user': c.user or c.author, 'extras_as_string': True,
+ 'for_view': True}
+ data_dict = {
+ 'type_filter': base.request.params.get('type', '')
+ }
+
+ params_nopage = [(k, v) for k,v in base.request.params.items()
+ if k != 'page']
+ try:
+ page = int(base.request.params.get('page', 1))
+ except ValueError, e:
+ abort(400, ('"page" parameter must be an integer'))
+
+ # Update ordering in the context
+ query = logic.get_action('related_list')(context,data_dict)
+
+ def search_url(params):
+ url = h.url_for(controller='related', action='dashboard')
+ params = [(k, v.encode('utf-8')
+ if isinstance(v, basestring) else str(v))
+ for k, v in params]
+ return url + u'?' + urllib.urlencode(params)
+ def pager_url(q=None, page=None):
+ params = list(params_nopage)
+ params.append(('page', page))
+ return search_url(params)
+
+
+ c.page = h.Page(
+ collection=query.all(),
+ page=page,
+ url=pager_url,
+ item_count=query.count(),
+ items_per_page=8
+ )
+
+ c.filters = dict(params_nopage)
+
+ return base.render( "related/dashboard.html")
+
+
+ def list(self, id):
+ """ List all related items for a specific dataset """
context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'extras_as_string': True,
'for_view': True}
@@ -32,5 +78,5 @@ def list(self, id):
c.related_count = len(c.pkg.related)
- return base.render( "package/related_list.html")
+ return base.render( "related/related_list.html")
diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py
index b2afe94..b0e315e 100644
--- a/ckan/logic/action/get.py
+++ b/ckan/logic/action/get.py
@@ -138,8 +138,8 @@ def related_show(context, data_dict=None):
def related_list(context, data_dict=None):
"""
- List the related items for a specific package which should be
- mentioned in the data_dict
+ List the related items which may be for a specific package which
+ should be mentioned in the data_dict
context:
model - The CKAN model module
@@ -150,6 +150,9 @@ def related_list(context, data_dict=None):
id - The ID of the dataset to which we want to list related items
or
dataset - The dataset (package) model
+
+ If neither value is in the data_dict then all related items will
+ be returned, and the ordering requested will be applied.
"""
model = context['model']
session = context['session']
@@ -158,14 +161,18 @@ def related_list(context, data_dict=None):
if not dataset:
dataset = model.Package.get(data_dict.get('id'))
- if not dataset:
- raise NotFound
-
check_access('related_show',context, data_dict)
- relateds = model.Related.get_for_dataset(dataset, status='active')
- related_items = (r.related for r in relateds)
- related_list = model_dictize.related_list_dictize( related_items, context)
+ related_list = []
+ if not dataset:
+ related_list = model.Session.query(model.Related)
+ tfilter = data_dict.get('type_filter', None)
+ if tfilter:
+ related_list = related_list.filter(model.Related.type == tfilter)
+ else:
+ relateds = model.Related.get_for_dataset(dataset, status='active')
+ related_items = (r.related for r in relateds)
+ related_list = model_dictize.related_list_dictize( related_items, context)
return related_list
diff --git a/ckan/templates/_snippet/add-related.html b/ckan/templates/_snippet/add-related.html
deleted file mode 100644
index e5b2a64..0000000
--- a/ckan/templates/_snippet/add-related.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<html
- xmlns="http://www.w3.org/1999/xhtml"
- xmlns:i18n="http://genshi.edgewall.org/i18n"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- py:strip=""
->
-<div class="modal-add-related modal fade in" style="display: none"
- py:def="add_related(dataset)">
- <div class="modal-header">
- <a class="close" data-dismiss="modal">×</a>
- <h3 class="heading">Add related item</h3>
- </div>
- <div class="modal-body">
- <form id="form-add-related" action="" method="POST" class="well">
- <div class="control-group">
- <input id="related-dataset" type="hidden" name="dataset_id" value="${c.pkg.id}"/>
- <label for="related-title">Title <span class="required">(required)</span></label>
- <input id="related-title" name="title" class="span6" placeholder="Please add the title for the item"/>
- </div>
- <div class="control-group">
- <label for="related-type">Type of item</label>
- <select id="related-type" name="type" class="span6 chzn-select">
- <option value="app">Application</option>
- <option value="idea">Idea</option>
- <option value="visualization">Visualization</option>
- </select>
- </div>
- <div class="control-group">
- <label for="related-description">Description</label>
- <textarea id="related-description" name="description" class="input-xlarge span6" rows="4" placeholder="Please describe the item"></textarea>
- </div>
- <div class="control-group">
- <label for="related-url">URL <span class="required">(required)</span></label>
- <input id="related-url" name="url" type="url" class="span6" placeholder="Please add a url"/>
- </div>
- <div class="control-group">
- <label for="related-image-url">Image URL</label>
- <input id="related-image-url" name="image_url" type="url" class="span6" placeholder="Please add a link to the image"/>
- </div>
- <div>
- <button type="submit" class="btn btn-primary">Submit</button>
- <button type="button" class="btn" data-dismiss="modal">Cancel</button>
- </div>
- </form>
- </div>
-</div>
-</html>
diff --git a/ckan/templates/_util.html b/ckan/templates/_util.html
index 5aa7c07..73f976f 100644
--- a/ckan/templates/_util.html
+++ b/ckan/templates/_util.html
@@ -125,10 +125,10 @@
</py:def>
- <py:def function="related_summary(related)">
+ <py:def function="related_summary(related, allow_delete)">
<li class="span3">
<div class="thumbnail">
- <button py:if="c.user and (c.userobj.id == related.owner_id or h.check_access('package_update',{'id':c.pkg.id}))" class="close" onclick="related_delete('${related.id}');">×</button>
+ <button py:if="allow_delete and c.user and (c.userobj.id == related.owner_id or h.check_access('package_update',{'id':c.pkg.id}))" class="close" onclick="related_delete('${related.id}');">×</button>
<a href="${related.url}" class="image">
<img src="${related.image_url}" width="210" py:if="related.image_url" />
<img src="/images/photo-placeholder.png" width="210" py:if="not related.image_url" />
diff --git a/ckan/templates/package/related_list.html b/ckan/templates/package/related_list.html
deleted file mode 100644
index baced80..0000000
--- a/ckan/templates/package/related_list.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<html xmlns:py="http://genshi.edgewall.org/"
- xmlns:i18n="http://genshi.edgewall.org/i18n"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xmlns:foaf="http://xmlns.com/foaf/0.1/"
- xmlns:owl="http://www.w3.org/2002/07/owl#"
- xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
- xmlns:dc="http://purl.org/dc/terms/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:dcat="http://www.w3.org/ns/dcat#"
- typeof="dcat:Dataset"
- about=""
- py:strip="">
-
- <py:def function="body_class">no-sidebar</py:def>
- <xi:include href="../_snippet/add-related.html" />
-
- <py:def function="page_title">${c.pkg_dict.get('title', c.pkg_dict['name'])}
- - Related</py:def>
-
- <py:def function="page_heading" property="dc:title">
- ${c.pkg_dict['title']} - Related
- </py:def>
-
- <div py:match="content">
- ${add_related(c.pkg)}
- <h3>Related items <a class="btn btn-small btn-primary pull-right" data-toggle="modal" href=".modal-add-related" py:if="c.user"><i class="icon-plus-sign icon-white"></i> Add related item</a></h3>
- <div>
- <div py:if="not c.pkg.related" class="span8 no-related-items">
- There are no related items here yet<span py:if="c.user">, why not <a data-toggle="modal" href=".modal-add-related">add one</a>?</span>
- </div>
-
- <ul class="related-items thumbnails">
- <py:for each="related in c.pkg.related">
- ${related_summary(related)}
- </py:for>
- </ul>
- </div>
-
- <span class="insert-comment-thread"></span>
- </div>
-
- <py:def function="optional_head">
- <script type="text/javascript" py:if="c.user">
- function related_delete(related_id) {
- var data = { 'id' : related_id }
- $.ajax({
- type: "post",
- url: CKAN.SITE_URL + '/api/3/action/related_delete',
- data: JSON.stringify(data),
- success: function (data) {
- window.location.reload();
- },
- error: function(err, txt, w) {
- // This needs to be far more informative.
- var msg = '<strong>Error:</strong> Unable to delete related item';
- $('<div class="alert alert-error" />').html(msg).hide().prependTo($('div#main')).fadeIn();
- }
- });
-
- }
- </script>
- <py:if test="config.get('rdf_packages')">
- <link rel="alternate" type="application/rdf+xml" title="RDF/XML" href="${config['rdf_packages'] + '/' + c.pkg.id + '.rdf' }" />
- <link rel="alternate" type="application/turtle" title="RDF/Turtle" href="${config['rdf_packages'] + '/' + c.pkg.id + '.ttl' }" />
- </py:if>
- </py:def>
-
- <py:def function="optional_feed">
- <link rel="alternate" type="application/atom+xml" title="Dataset History"
- href="${h.url(controller='package', action='history', id=c.pkg.name, format='atom', days=7)}" />
- </py:def>
-
- <xi:include href="layout.html" />
-</html>
-
diff --git a/ckan/templates/related/add-related.html b/ckan/templates/related/add-related.html
new file mode 100644
index 0000000..e5b2a64
--- /dev/null
+++ b/ckan/templates/related/add-related.html
@@ -0,0 +1,48 @@
+<html
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:i18n="http://genshi.edgewall.org/i18n"
+ xmlns:py="http://genshi.edgewall.org/"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ py:strip=""
+>
+<div class="modal-add-related modal fade in" style="display: none"
+ py:def="add_related(dataset)">
+ <div class="modal-header">
+ <a class="close" data-dismiss="modal">×</a>
+ <h3 class="heading">Add related item</h3>
+ </div>
+ <div class="modal-body">
+ <form id="form-add-related" action="" method="POST" class="well">
+ <div class="control-group">
+ <input id="related-dataset" type="hidden" name="dataset_id" value="${c.pkg.id}"/>
+ <label for="related-title">Title <span class="required">(required)</span></label>
+ <input id="related-title" name="title" class="span6" placeholder="Please add the title for the item"/>
+ </div>
+ <div class="control-group">
+ <label for="related-type">Type of item</label>
+ <select id="related-type" name="type" class="span6 chzn-select">
+ <option value="app">Application</option>
+ <option value="idea">Idea</option>
+ <option value="visualization">Visualization</option>
+ </select>
+ </div>
+ <div class="control-group">
+ <label for="related-description">Description</label>
+ <textarea id="related-description" name="description" class="input-xlarge span6" rows="4" placeholder="Please describe the item"></textarea>
+ </div>
+ <div class="control-group">
+ <label for="related-url">URL <span class="required">(required)</span></label>
+ <input id="related-url" name="url" type="url" class="span6" placeholder="Please add a url"/>
+ </div>
+ <div class="control-group">
+ <label for="related-image-url">Image URL</label>
+ <input id="related-image-url" name="image_url" type="url" class="span6" placeholder="Please add a link to the image"/>
+ </div>
+ <div>
+ <button type="submit" class="btn btn-primary">Submit</button>
+ <button type="button" class="btn" data-dismiss="modal">Cancel</button>
+ </div>
+ </form>
+ </div>
+</div>
+</html>
diff --git a/ckan/templates/related/dashboard.html b/ckan/templates/related/dashboard.html
new file mode 100644
index 0000000..fc519b7
--- /dev/null
+++ b/ckan/templates/related/dashboard.html
@@ -0,0 +1,56 @@
+<html xmlns:py="http://genshi.edgewall.org/"
+ xmlns:i18n="http://genshi.edgewall.org/i18n"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:owl="http://www.w3.org/2002/07/owl#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:dc="http://purl.org/dc/terms/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:dcat="http://www.w3.org/ns/dcat#"
+ typeof="dcat:Dataset"
+ about=""
+ py:strip="">
+
+ <py:def function="body_class">no-sidebar</py:def>
+ <xi:include href="add-related.html" />
+
+ <py:def function="page_title">Apps</py:def>
+
+ <py:def function="page_heading" property="dc:title">
+ Applications
+ </py:def>
+
+ <div py:match="content">
+ <h4 py:if="c.page.item_count">Showing items <strong>${c.page.first_item} - ${c.page.last_item}</strong> of <strong>${c.page.item_count}</strong> related items found</h4>
+ <h4 py:if="not c.page.item_count"><strong>${c.page.item_count}</strong> related items found</h4>
+
+ <div class="well">
+ <form action="" method="get" class="form-horizontal">
+ <input type='hidden' name='page' value='1'/>
+
+ <label for="type">Filter by type</label>
+ <select name="type">
+ <option value="">All</option>
+ <option value="app" py:attrs="{'selected': 'selected' if c.filters.get('type') == 'app' else None}">Application</option>
+ <option value="idea" py:attrs="{'selected': 'selected' if c.filters.get('type') == 'idea' else None}">Idea</option>
+ <option value="visualization" py:attrs="{'selected': 'selected' if c.filters.get('type') == 'visualization' else None}">Visualization</option>
+ </select>
+
+ <button class="btn btn-primary pull-right">Apply</button>
+ </form>
+ </div>
+
+ <ul class="related-items thumbnails">
+ <py:for each="related in c.page.items">
+ ${related_summary(related,False)}
+ </py:for>
+ </ul>
+
+ ${c.page.pager()}
+
+ <span class="insert-comment-thread"></span>
+ </div>
+
+ <xi:include href="../layout.html" />
+</html>
+
diff --git a/ckan/templates/related/related_list.html b/ckan/templates/related/related_list.html
new file mode 100644
index 0000000..324c381
--- /dev/null
+++ b/ckan/templates/related/related_list.html
@@ -0,0 +1,75 @@
+<html xmlns:py="http://genshi.edgewall.org/"
+ xmlns:i18n="http://genshi.edgewall.org/i18n"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:owl="http://www.w3.org/2002/07/owl#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:dc="http://purl.org/dc/terms/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:dcat="http://www.w3.org/ns/dcat#"
+ typeof="dcat:Dataset"
+ about=""
+ py:strip="">
+
+ <py:def function="body_class">no-sidebar</py:def>
+ <xi:include href="add-related.html" />
+
+ <py:def function="page_title">${c.pkg_dict.get('title', c.pkg_dict['name'])}
+ - Related</py:def>
+
+ <py:def function="page_heading" property="dc:title">
+ ${c.pkg_dict['title']} - Related
+ </py:def>
+
+ <div py:match="content">
+ ${add_related(c.pkg)}
+ <h3>Related items <a class="btn btn-small btn-primary pull-right" data-toggle="modal" href=".modal-add-related" py:if="c.user"><i class="icon-plus-sign icon-white"></i> Add related item</a></h3>
+ <div>
+ <div py:if="not c.pkg.related" class="span8 no-related-items">
+ There are no related items here yet<span py:if="c.user">, why not <a data-toggle="modal" href=".modal-add-related">add one</a>?</span>
+ </div>
+
+ <ul class="related-items thumbnails">
+ <py:for each="related in c.pkg.related">
+ ${related_summary(related, True)}
+ </py:for>
+ </ul>
+ </div>
+
+ <span class="insert-comment-thread"></span>
+ </div>
+
+ <py:def function="optional_head">
+ <script type="text/javascript" py:if="c.user">
+ function related_delete(related_id) {
+ var data = { 'id' : related_id }
+ $.ajax({
+ type: "post",
+ url: CKAN.SITE_URL + '/api/3/action/related_delete',
+ data: JSON.stringify(data),
+ success: function (data) {
+ window.location.reload();
+ },
+ error: function(err, txt, w) {
+ // This needs to be far more informative.
+ var msg = '<strong>Error:</strong> Unable to delete related item';
+ $('<div class="alert alert-error" />').html(msg).hide().prependTo($('div#main')).fadeIn();
+ }
+ });
+
+ }
+ </script>
+ <py:if test="config.get('rdf_packages')">
+ <link rel="alternate" type="application/rdf+xml" title="RDF/XML" href="${config['rdf_packages'] + '/' + c.pkg.id + '.rdf' }" />
+ <link rel="alternate" type="application/turtle" title="RDF/Turtle" href="${config['rdf_packages'] + '/' + c.pkg.id + '.ttl' }" />
+ </py:if>
+ </py:def>
+
+ <py:def function="optional_feed">
+ <link rel="alternate" type="application/atom+xml" title="Dataset History"
+ href="${h.url(controller='package', action='history', id=c.pkg.name, format='atom', days=7)}" />
+ </py:def>
+
+ <xi:include href="../package/layout.html" />
+</html>
+
================================================================
More information about the ckan-changes
mailing list