[ckan-changes] commit/ckan: 4 new changesets
Bitbucket
commits-noreply at bitbucket.org
Wed Sep 21 11:04:22 UTC 2011
4 new changesets in ckan:
http://bitbucket.org/okfn/ckan/changeset/f4d41c0af259/
changeset: f4d41c0af259
branch: feature-1302-resource-tag-search
user: John Glover
date: 2011-09-20 17:39:21
summary: [search] Remove query and terms arguments from resource search query, not used
affected #: 1 file (-1 bytes)
--- a/ckan/lib/search/query.py Tue Sep 20 15:49:18 2011 +0100
+++ b/ckan/lib/search/query.py Tue Sep 20 16:39:21 2011 +0100
@@ -237,7 +237,7 @@
class ResourceSearchQuery(SearchQuery):
"""Search for resources."""
- def run(self, query=None, terms=[], fields={}, facet_by=[], options=None, **kwargs):
+ def run(self, fields={}, options=None, **kwargs):
if options is None:
options = QueryOptions(**kwargs)
else:
@@ -255,7 +255,7 @@
# if options.all_fields is set, return a dict
# if not, return a list of resource IDs
if options.all_fields:
- results['results'] = [r.as_dict() for r in results['results']]
+ results['results'] = [r.as_dict() for r in results['results']]
else:
results['results'] = [r.id for r in results['results']]
return results
http://bitbucket.org/okfn/ckan/changeset/3ab7ea861258/
changeset: 3ab7ea861258
branch: feature-1302-resource-tag-search
user: John Glover
date: 2011-09-20 18:04:03
summary: [search] Add basic tests for tag search
affected #: 1 file (-1 bytes)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ckan/tests/lib/test_tag_search.py Tue Sep 20 17:04:03 2011 +0100
@@ -0,0 +1,45 @@
+from nose.tools import assert_raises
+from ckan.tests import *
+from ckan.tests import is_search_supported
+import ckan.lib.search as search
+from ckan import model
+from ckan.lib.create_test_data import CreateTestData
+
+class TestTagSearch(object):
+ @classmethod
+ def setup_class(self):
+ if not is_search_supported():
+ raise SkipTest("Search not supported")
+ CreateTestData.create()
+
+ @classmethod
+ def teardown_class(self):
+ model.repo.rebuild_db()
+
+ def test_good_search_terms(self):
+ result = search.query_for(model.Tag).run(terms=[u'ru'])
+ assert result['count'] == 1, result
+ assert 'russian' in result['results'], result
+
+ result = search.query_for(model.Tag).run(terms=[u's'])
+ assert result['count'] == 2, result
+ assert 'russian' in result['results'], result
+ assert 'tolstoy' in result['results'], result
+
+ def test_bad_search_terms(self):
+ result = search.query_for(model.Tag).run(terms=[u'asdf'])
+ assert result['count'] == 0, result
+
+ def test_good_search_fields(self):
+ result = search.query_for(model.Tag).run(fields={'tags': u'ru'})
+ assert result['count'] == 1, result
+ assert 'russian' in result['results'], result
+
+ result = search.query_for(model.Tag).run(fields={'tags': u's'})
+ assert result['count'] == 2, result
+ assert 'russian' in result['results'], result
+ assert 'tolstoy' in result['results'], result
+
+ def test_bad_search_fields(self):
+ result = search.query_for(model.Tag).run(fields={'tags': u'asdf'})
+ assert result['count'] == 0, result
http://bitbucket.org/okfn/ckan/changeset/f7115e152825/
changeset: f7115e152825
branch: feature-1302-resource-tag-search
user: John Glover
date: 2011-09-21 12:02:44
summary: [search] Move tag search function to logic layer, remove CKAN query parser
affected #: 4 files (-1 bytes)
--- a/ckan/lib/search/query.py Tue Sep 20 17:04:03 2011 +0100
+++ b/ckan/lib/search/query.py Wed Sep 21 11:02:44 2011 +0100
@@ -1,7 +1,5 @@
-from sqlalchemy import or_
import json
from pylons import config
-from paste.util.multidict import MultiDict
from paste.deploy.converters import asbool
from ckan import model
from ckan.logic import get_action
@@ -61,91 +59,6 @@
self[name] = value
-class QueryParser(object):
- """
- The query parser will take any incoming query specifications and turn
- them into field-specific and general query parts.
- """
-
- def __init__(self, query, terms, fields):
- self._query = query
- self._terms = terms
- self._fields = MultiDict(fields)
-
- @property
- def query(self):
- if not hasattr(self, '_combined_query'):
- parts = [self._query if self._query is not None else '']
-
- for term in self._terms:
- if term.find(u' ') != -1:
- term = u"\"%s\"" % term
- parts.append(term.strip())
-
- for field, value in self._fields.items():
- if field != 'tags' and value.find(' ') != -1:
- value = u"\"%s\"" % value
- parts.append(u"%s:%s" % (field.strip(), value.strip()))
-
- self._combined_query = u' '.join(parts)
- return self._combined_query
-
- def _query_tokens(self):
- """ Split the query string, leaving quoted strings intact. """
- if self._query:
- inside_quote = False
- buf = u''
- for ch in self._query:
- if ch == u' ' and not inside_quote:
- if len(buf):
- yield buf.strip()
- buf = u''
- elif ch == inside_quote:
- inside_quote = False
- elif ch in [u"\"", u"'"]:
- inside_quote = ch
- else:
- buf += ch
- if len(buf):
- yield buf.strip()
-
- def _parse_query(self):
- """ Decompose the query string into fields and terms. """
- self._combined_fields = MultiDict(self._fields)
- self._combined_terms = list(self._terms)
- for token in self._query_tokens():
- colon_pos = token.find(u':')
- if colon_pos != -1:
- field = token[:colon_pos]
- value = token[colon_pos+1:]
- value = value.strip('"').strip("'").strip()
- self._combined_fields.add(field, value)
- else:
- self._combined_terms.append(token)
-
- @property
- def fields(self):
- if not hasattr(self, '_combined_fields'):
- self._parse_query()
- return self._combined_fields
-
- @property
- def terms(self):
- if not hasattr(self, '_combined_terms'):
- self._parse_query()
- return self._combined_terms
-
- def validate(self):
- """ Check that this is a valid query. """
- pass
-
- def __str__(self):
- return self.query
-
- def __repr__(self):
- return "Query(%r)" % self.query
-
-
class SearchQuery(object):
"""
A query is ... when you ask the search engine things. SearchQuery is intended
@@ -169,14 +82,6 @@
_open_licenses.append(license.id)
return _open_licenses
- def _format_results(self):
- if not self.options.return_objects and len(self.results):
- if self.options.all_fields:
- self.results = [r.as_dict() for r in self.results]
- else:
- attr_name = self.options.ref_entity_with_attr
- self.results = [getattr(entity, attr_name) for entity in self.results]
-
def get_all_entity_ids(self, max_results=1000):
"""
Return a list of the IDs of all indexed packages.
@@ -184,55 +89,40 @@
return []
def run(self, query=None, terms=[], fields={}, facet_by=[], options=None, **kwargs):
+ raise SearchError("SearchQuery.run() not implemented!")
+
+ # convenience, allows to query(..)
+ __call__ = run
+
+
+class TagSearchQuery(SearchQuery):
+ """Search for tags."""
+ def run(self, query=[], fields={}, options=None, **kwargs):
if options is None:
options = QueryOptions(**kwargs)
else:
options.update(kwargs)
- self.options = options
- self.options.validate()
- self.facet_by = facet_by
- self.facets = dict()
- self.query = QueryParser(query, terms, fields)
- self.query.validate()
- self._run()
- self._format_results()
- return {'results': self.results, 'count': self.count}
+
+ context = {'model': model, 'session': model.Session}
+ data_dict = {
+ 'query': query,
+ 'fields': fields,
+ 'offset': options.get('offset'),
+ 'limit': options.get('limit')
+ }
+ results = get_action('tag_search')(context, data_dict)
+
+ if not options.return_objects:
+ # if options.all_fields is set, return a dict
+ # if not, return a list of resource IDs
+ if options.all_fields:
+ results['results'] = [r.as_dict() for r in results['results']]
+ else:
+ results['results'] = [r.name for r in results['results']]
- def _run(self):
- raise SearchError("SearchQuery._run() not implemented!")
-
- def _db_query(self, q):
- # Run the query
- self.count = q.count()
- q = q.offset(self.options.get('offset'))
- q = q.limit(self.options.get('limit'))
-
- self.results = []
- for result in q:
- if isinstance(result, tuple) and isinstance(result[0], model.DomainObject):
- # This is the case for order_by rank due to the add_column.
- self.results.append(result[0])
- else:
- self.results.append(result)
-
- # convenience, allows to query(..)
- __call__ = run
-
-
-class TagSearchQuery(SearchQuery):
- """Search for tags."""
- def _run(self):
- q = model.Session.query(model.Tag)
- q = q.distinct().join(model.Tag.package_tags)
- terms = list(self.query.terms)
- for field, value in self.query.fields.items():
- if field in ('tag', 'tags'):
- terms.append(value)
- if not len(terms):
- return
- for term in terms:
- q = q.filter(model.Tag.name.contains(term.lower()))
- self._db_query(q)
+ self.count = results['count']
+ self.results = results['results']
+ return results
class ResourceSearchQuery(SearchQuery):
@@ -252,12 +142,16 @@
}
results = get_action('resource_search')(context, data_dict)
- # if options.all_fields is set, return a dict
- # if not, return a list of resource IDs
- if options.all_fields:
- results['results'] = [r.as_dict() for r in results['results']]
- else:
- results['results'] = [r.id for r in results['results']]
+ if not options.return_objects:
+ # if options.all_fields is set, return a dict
+ # if not, return a list of resource IDs
+ if options.all_fields:
+ results['results'] = [r.as_dict() for r in results['results']]
+ else:
+ results['results'] = [r.id for r in results['results']]
+
+ self.count = results['count']
+ self.results = results['results']
return results
--- a/ckan/logic/action/get.py Tue Sep 20 17:04:03 2011 +0100
+++ b/ckan/logic/action/get.py Wed Sep 21 11:02:44 2011 +0100
@@ -500,16 +500,14 @@
check_access('tag_autocomplete', context, data_dict)
- q = data_dict.get('q',None)
+ q = data_dict.get('q', None)
if not q:
return []
limit = data_dict.get('limit',10)
- like_q = u"%s%%" % q
-
query = query_for('tag')
- query.run(query=like_q,
+ query.run(query=q,
return_objects=True,
limit=10,
username=user)
@@ -676,3 +674,33 @@
results.append(result)
return {'count': count, 'results': results}
+
+def tag_search(context, data_dict):
+ model = context['model']
+ session = context['session']
+
+ query = data_dict.get('query')
+ terms = [query] if query else []
+
+ fields = data_dict.get('fields', {})
+ offset = data_dict.get('offset')
+ limit = data_dict.get('limit')
+
+ # TODO: should we check for user authentication first?
+ q = model.Session.query(model.Tag)
+ q = q.distinct().join(model.Tag.package_tags)
+ for field, value in fields.items():
+ if field in ('tag', 'tags'):
+ terms.append(value)
+
+ if not len(terms):
+ return
+
+ for term in terms:
+ q = q.filter(model.Tag.name.contains(term.lower()))
+
+ count = q.count()
+ q = q.offset(offset)
+ q = q.limit(limit)
+ results = [r for r in q]
+ return {'count': count, 'results': results}
--- a/ckan/tests/functional/api/test_action.py Tue Sep 20 17:04:03 2011 +0100
+++ b/ckan/tests/functional/api/test_action.py Wed Sep 21 11:02:44 2011 +0100
@@ -459,7 +459,6 @@
postparams = '%s=1' % json.dumps({'q':'r'})
res = self.app.post('/api/action/tag_autocomplete', params=postparams)
res_obj = json.loads(res.body)
- print res_obj
assert res_obj == {
'help': 'Returns tags containing the provided string',
'result': ['russian'],
--- a/ckan/tests/lib/test_tag_search.py Tue Sep 20 17:04:03 2011 +0100
+++ b/ckan/tests/lib/test_tag_search.py Wed Sep 21 11:02:44 2011 +0100
@@ -16,18 +16,18 @@
def teardown_class(self):
model.repo.rebuild_db()
- def test_good_search_terms(self):
- result = search.query_for(model.Tag).run(terms=[u'ru'])
+ def test_good_search_query(self):
+ result = search.query_for(model.Tag).run(query=u'ru')
assert result['count'] == 1, result
assert 'russian' in result['results'], result
- result = search.query_for(model.Tag).run(terms=[u's'])
+ result = search.query_for(model.Tag).run(query=u's')
assert result['count'] == 2, result
assert 'russian' in result['results'], result
assert 'tolstoy' in result['results'], result
- def test_bad_search_terms(self):
- result = search.query_for(model.Tag).run(terms=[u'asdf'])
+ def test_bad_search_query(self):
+ result = search.query_for(model.Tag).run(query=u'asdf')
assert result['count'] == 0, result
def test_good_search_fields(self):
http://bitbucket.org/okfn/ckan/changeset/05ab5cc99251/
changeset: 05ab5cc99251
branch: feature-1302-resource-tag-search
user: John Glover
date: 2011-09-21 13:04:00
summary: merge with default
affected #: 31 files (-1 bytes)
--- a/ckan/controllers/package.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/controllers/package.py Wed Sep 21 12:04:00 2011 +0100
@@ -110,8 +110,6 @@
abort(401, _('Not authorized to see this page'))
q = c.q = request.params.get('q', u'') # unicode format (decoded from utf8)
- c.open_only = request.params.get('open_only', 0)
- c.downloadable_only = request.params.get('downloadable_only', 0)
c.query_error = False
try:
page = int(request.params.get('page', 1))
@@ -144,7 +142,7 @@
try:
c.fields = []
for (param, value) in request.params.items():
- if not param in ['q', 'open_only', 'downloadable_only', 'page'] \
+ if not param in ['q', 'page'] \
and len(value) and not param.startswith('_'):
c.fields.append((param, value))
q += ' %s: "%s"' % (param, value)
@@ -157,8 +155,6 @@
'facet.field':g.facets,
'rows':limit,
'start':(page-1)*limit,
- 'filter_by_openness':c.open_only,
- 'filter_by_downloadable':c.downloadable_only,
}
query = get_action('package_search')(context,data_dict)
--- a/ckan/controllers/user.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/controllers/user.py Wed Sep 21 12:04:00 2011 +0100
@@ -169,7 +169,6 @@
def edit(self, id=None, data=None, errors=None, error_summary=None):
context = {'model': model, 'session': model.Session,
'user': c.user or c.author,
- 'preview': 'preview' in request.params,
'save': 'save' in request.params,
'schema': self._edit_form_to_db_schema(),
}
@@ -180,7 +179,7 @@
abort(400, _('No user specified'))
data_dict = {'id': id}
- if (context['save'] or context['preview']) and not data:
+ if (context['save']) and not data:
return self._save_edit(id, context)
try:
@@ -210,6 +209,7 @@
self._setup_template_variables(context)
+ c.is_myself = True
c.form = render(self.edit_user_form, extra_vars=vars)
return render('user/edit.html')
@@ -222,15 +222,6 @@
data_dict['id'] = id
user = get_action('user_update')(context, data_dict)
- if context['preview']:
- about = request.params.getone('about')
- c.preview = self._format_about(about)
- c.user_about = about
- c.full_name = request.params.get('fullname','')
- c.email = request.params.getone('email')
-
- return self.edit(id, data_dict)
-
h.redirect_to(controller='user', action='read', id=user['id'])
except NotAuthorized:
abort(401, _('Unauthorized to edit user %s') % id)
--- a/ckan/lib/search/__init__.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/lib/search/__init__.py Wed Sep 21 12:04:00 2011 +0100
@@ -12,8 +12,6 @@
DEFAULT_OPTIONS = {
'limit': 20,
'offset': 0,
- 'filter_by_openness': False,
- 'filter_by_downloadable': False,
# about presenting the results
'order_by': 'rank',
'return_objects': False,
--- a/ckan/logic/action/update.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/logic/action/update.py Wed Sep 21 12:04:00 2011 +0100
@@ -339,7 +339,6 @@
model = context['model']
user = context['user']
- preview = context.get('preview', False)
schema = context.get('schema') or default_update_user_schema()
id = data_dict['id']
@@ -357,11 +356,8 @@
user = user_dict_save(data, context)
- if not preview:
- model.repo.commit()
- return user_dictize(user, context)
-
- return data
+ model.repo.commit()
+ return user_dictize(user, context)
## Modifications for rest api
--- a/ckan/public/css/style.css Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/public/css/style.css Wed Sep 21 12:04:00 2011 +0100
@@ -1,3 +1,4 @@
+ at import url('/css/forms.css');
.header.outer {
background-color: #e2e2e2;
@@ -176,6 +177,22 @@
#minornavigation ul.tabbed li.action {
float: right;
}
+#minornavigation li {
+ border: 1px solid transparent;
+}
+#minornavigation li.current-tab {
+ background: #000;
+ background-color: #fff;
+ border: 1px solid #aaa;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+}
+#minornavigation li.current-tab a,
+#minornavigation li.current-tab a:hover,
+#minornavigation li.current-tab a:visited {
+ color: #222;
+}
/* Side bar widgets */
ul.widget-list {
@@ -262,13 +279,14 @@
#minornavigation ul {
list-style: none;
- padding: 7px;
+ padding: 1px;
margin: 0;
}
#minornavigation ul li {
display: inline-block;
- margin-right: 2em;
+ margin-right: 3px;
+ padding: 5px 11px 5px 9px
}
#minornavigation ul li a {
@@ -711,11 +729,23 @@
display: none;
}
-body.edit.package div#content {
+body.package.edit div#content {
+ margin-right: 29px;
+ margin-left: 0px;
+ float: right;
+ padding-right: 0;
+ padding-left: 20px;
+ border: none;
+ border-left: 1px solid #eee;
+}
+body.package.edit div#sidebar {
+ padding-left: 0px;
+ float: left;
margin-right: 0px;
}
-body.edit.package div#sidebar {
- padding-left: 0px;
+body.package.edit ul.widget-list {
+ margin-left: 1.5em;
+ margin-right: 0;
}
ul.edit-form-navigation {
list-style-type: none;
@@ -741,16 +771,13 @@
background-image: linear-gradient(top, #f0f0f0, #e2e2e2);
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#f0f0f0', EndColorStr='#e2e2e2');
- border-left: none;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- -moz-border-bottom-left-radius: 0px;
- -webkit-border-bottom-left-radius: 0px;
- border-bottom-left-radius: 0px;
- -moz-border-top-left-radius: 0px;
- -webkit-border-top-left-radius: 0px;
- border-top-left-radius: 0px;
+ border-right: none;
+ -moz-border-radius-bottomleft: 5px;
+ -webkit-border-bottom-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+ -moz-border-radius-topleft: 5px;
+ -webkit-border-top-left-radius: 5px;
+ border-top-left-radius: 5px;
-moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box;
}
@@ -762,6 +789,7 @@
-moz-border-radius: 5px;
border: 1px solid #CCC;
padding: 0 5px 5px 10px;
+ width: 32em;
}
div.markdown-preview {
@@ -816,6 +844,23 @@
float: right;
}
+div.resource-add {
+ background: #eee;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ border: 1px solid #e0e0e0;
+ border-left: none;
+ border-right: none;
+}
+div.resource-add li h4 {
+ display: inline;
+ padding-right: 20px;
+}
+div.resource-add-subpane {
+ margin-top: 10px;
+}
+
+
/* ==================== */
/* = Add Dataset Page = */
/* ==================== */
@@ -894,11 +939,15 @@
ul.tabs li a {
display: inline-block;
padding: 2px 8px;
+ margin-right: 10px;
font-size: 10px;
font-weight: bold;
text-decoration: none;
color: #666;
- border: 1px solid transparent;
+ border: 1px solid #DDD;
+ border-color: #DDD;
+ border-right-color: #BBB;
+ border-bottom-color: #BBB;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-top-left-radius: 10px 10px;
@@ -916,25 +965,138 @@
}
+/* ============================== */
+/* = Controller-specific tweaks = */
+/* ============================== */
+
+body.group.index #minornavigation {
+ visibility: hidden;
+}
+
+body.package.search #minornavigation {
+ visibility: hidden;
+}
+body.package.search #menusearch {
+ display: none;
+}
+
+body.index.home #minornavigation {
+ display: none;
+}
+
+body.index.home #sidebar {
+ display: none;
+}
+
+body.index.home .front-page .action-box h1 {
+ padding-top: 0.6em;
+ padding-bottom: 0.5em;
+ font-size: 2.1em;
+}
+
+body.index.home .front-page .action-box {
+ border-radius: 20px;
+ background: #FFF7C0;
+}
+
+body.index.home .front-page .action-box-inner {
+ margin: 20px;
+ margin-bottom: 5px;
+ min-height: 15em;
+}
+body.index.home .front-page .action-box-inner.collaborate {
+ background:url(/img/collaborate.png) no-repeat right top;
+}
+
+body.index.home .front-page .action-box-inner.share {
+ background:url(/img/share.png) no-repeat right top;
+}
+
+body.index.home .front-page .action-box-inner.find {
+ background:url(/img/find.png) no-repeat right top;
+}
+
+body.index.home .front-page .action-box-inner a {
+ font-weight: bold;
+}
+
+body.index.home .front-page .action-box-inner input {
+ font-family: 'Ubuntu';
+ border-radius: 10px;
+ background-color: #fff;
+ border: 0px;
+ font-size: 1.3em;
+ width: 90%;
+ border: 1px solid #999;
+ color: #666;
+ padding: 0.5em;
+}
+
+body.index.home .front-page .action-box-inner .create-button {
+ display: block;
+ float: right;
+ font-weight: normal;
+ font-family: 'Ubuntu';
+ margin-top: 1.5em;
+ border-radius: 10px;
+ background-color: #B22;
+ border: 0px;
+ font-size: 1.3em;
+ color: #fff;
+ padding: 0.5em;
+}
+
+body.index.home .front-page .action-box-inner .create-button:hover {
+ background-color: #822;
+}
+
+body.index.home .front-page .action-box-inner ul {
+margin-top: 1em;
+margin-bottom: 0;
+}
+
+body.index.home .front-page .whoelse {
+ margin-top: 1em;
+}
+
+body.index.home .front-page .group {
+ overflow: hidden;
+}
+
+body.index.home .front-page .group h3 {
+ margin-bottom: 0.5em;
+}
+
+body.index.home .front-page .group p {
+ margin-bottom: 0em;
+ min-height: 6em;
+}
+
+body.index.home .front-page .group strong {
+ display: block;
+ margin-bottom: 1.5em;
+}
+
+
/* ================================== */
/* = Twitter.Bootstrap Form Buttons = */
/* ================================== */
div.form-submit {
- background: #eee;
- padding: 20px;
- margin-bottom: 8px;
- border: 1px solid #ccc;
- border-left: none;
- border-right: none;
- height: 60px;
+ background: #eee;
+ padding: 20px;
+ margin-bottom: 8px;
+ border: 1px solid #ccc;
+ border-left: none;
+ border-right: none;
}
-
div.form-submit p.hints {
- display: block;
- width: 50%;
- float: right;
+ width: 50%;
+ float: right;
+ margin: 0;
}
-
+div.clear {
+ clear: both;
+}
.pretty-button {
cursor: pointer;
@@ -1044,5 +1206,16 @@
}
+/* ====================================== */
+/* = Correct mistakes made by blueprint = */
+/* ====================================== */
+body.success,
+body.error {
+ background: #fff;
+ padding: 0;
+ margin-bottom: 0;
+ border: none;
+ color: #000;
+}
--- a/ckan/public/scripts/application.js Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/public/scripts/application.js Wed Sep 21 12:04:00 2011 +0100
@@ -20,11 +20,23 @@
var isDatasetNew = $('body.package.new').length > 0;
if (isDatasetNew) {
- $('#save').val("Add Dataset")
+ $('#save').val("Add Dataset");
}
+ // Buttons with href-action should navigate when clicked
+ $('input.href-action').click(function(e) {
+ e.preventDefault();
+ window.location = ($(e.target).attr('action'));
+ });
+
var isDatasetEdit = $('body.package.edit').length > 0;
if (isDatasetEdit) {
+ // Selectively enable the upload button
+ var storageEnabled = $.inArray('storage',CKAN.plugins)>=0;
+ if (storageEnabled) {
+ $('div.resource-add li.upload-file').show();
+ }
+
// Set up hashtag nagivigation
CKAN.Utils.setupDatasetEditNavigation();
--- a/ckan/public/scripts/templates.js Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/public/scripts/templates.js Wed Sep 21 12:04:00 2011 +0100
@@ -1,12 +1,3 @@
-
-CKAN.Templates.resourceAddChoice = ' \
- <ul> \
- <li>Add a resource:</li> \
- <li><a href="#" action="upload-file" class="action-resource-tab">Upload a file</a></li> \
- <li><a href="#" action="link-file" class="action-resource-tab">Link to a file</a></li> \
- <li><a href="#" action="link-api" class="action-resource-tab">Link to an API</a></li> \
- </ul> \
-';
CKAN.Templates.resourceAddLinkFile = ' \
<form class="resource-add" action=""> \
@@ -35,7 +26,7 @@
</label> \
</dt> \
<dd> \
- <input name="url" type="text" placeholder="http://mydataset.com/file.csv" style="width: 60%" /> \
+ <input name="url" type="text" placeholder="http://mydataset.com/api/" style="width: 60%" /> \
<input name="save" type="submit" class="pretty-button primary" value="Add" /> \
<input name="reset" type="reset" class="pretty-button" value="Cancel" /> \
</dd> \
@@ -80,12 +71,12 @@
<td class="resource-summary resource-url"> \
${resource.url} \
</td> \
+ <td class="resource-summary resource-name"> \
+ ${resource.name} \
+ </td> \
<td class="resource-summary resource-format"> \
${resource.format} \
</td> \
- <td class="resource-summary resource-description"> \
- ${resource.description} \
- </td> \
<td class="resource-expanded" colspan="3"> \
<div class="inner"> \
<table> \
@@ -97,8 +88,8 @@
</thead> \
<tbody> \
<tr> \
- <td style="display: none;" class="form-label">Name</td> \
- <td style="display: none;" class="form-value" colspan="3"> \
+ <td class="form-label">Name</td> \
+ <td class="form-value" colspan="3"> \
<input name="resources__${num}__name" type="text" value="${resource.name}" class="long" /> \
</td> \
</tr> \
--- a/ckan/templates/authorization_group/layout.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/authorization_group/layout.html Wed Sep 21 12:04:00 2011 +0100
@@ -8,11 +8,11 @@
<py:match path="minornavigation" py:if="c.authorization_group"><ul class="tabbed">
- <li>${h.subnav_link(c, h.icon('authorization_group') + _('View'), controller='authorization_group', action='read', id=c.authorization_group.name or c.authorization_group.id)}</li>
- <li py:if="h.check_access('authorization_group_update',{'id':c.authorization_group.id})">
+ <li py:attrs="{'class':'current-tab'} if c.action=='read' else {}">${h.subnav_link(c, h.icon('authorization_group') + _('View'), controller='authorization_group', action='read', id=c.authorization_group.name or c.authorization_group.id)}</li>
+ <li py:attrs="{'class':'current-tab'} if c.action=='edit' else {}" py:if="h.check_access('authorization_group_update',{'id':c.authorization_group.id})">
${h.subnav_link(c, h.icon('authorization_group_edit') + _('Edit'), controller='authorization_group', action='edit', id=c.authorization_group.name or c.authorization_group.id)}
</li>
- <li py:if="h.check_access('authorization_group_edit_permissions',{'id':c.authorization_group.id})">
+ <li py:attrs="{'class':'current-tab'} if c.action=='authz' else {}" py:if="h.check_access('authorization_group_edit_permissions',{'id':c.authorization_group.id})">
${h.subnav_link(c, h.icon('lock') + _('Authorization'), controller='authorization_group', action='authz', id=c.authorization_group.name or c.authorization_group.id)}
</li></ul>
--- a/ckan/templates/group/index.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/group/index.html Wed Sep 21 12:04:00 2011 +0100
@@ -6,10 +6,6 @@
<py:def function="page_title">Groups of Datasets</py:def><py:def function="page_heading">Groups of Datasets</py:def>
- <py:def function="optional_head">
- <style>#minornavigation { visibility: hidden; }</style>
- </py:def>
-
<div py:match="content">
${c.page.pager()}
--- a/ckan/templates/group/layout.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/group/layout.html Wed Sep 21 12:04:00 2011 +0100
@@ -23,12 +23,12 @@
<py:match path="minornavigation" py:if="c.group"><ul class="tabbed">
- <li>${h.subnav_link(c, h.icon('group') + _('View'), controller='group', action='read', id=c.group.name)}</li>
- <li py:if="h.check_access('group_update',{'id':c.group.id})">
+ <li py:attrs="{'class':'current-tab'} if c.action=='read' else {}">${h.subnav_link(c, h.icon('group') + _('View'), controller='group', action='read', id=c.group.name)}</li>
+ <li py:attrs="{'class':'current-tab'} if c.action=='edit' else {}" py:if="h.check_access('group_update',{'id':c.group.id})">
${h.subnav_link(c, h.icon('group_edit') + _('Edit'), controller='group', action='edit', id=c.group.name)}
</li>
- <li>${h.subnav_link(c, h.icon('page_white_stack') + _('History'), controller='group', action='history', id=c.group.name)}</li>
- <li py:if="h.check_access('group_edit_permissions',{'id':c.group.id})">
+ <li py:attrs="{'class':'current-tab'} if c.action=='history' else {}">${h.subnav_link(c, h.icon('page_white_stack') + _('History'), controller='group', action='history', id=c.group.name)}</li>
+ <li py:attrs="{'class':'current-tab'} if c.action=='authz' else {}" py:if="h.check_access('group_edit_permissions',{'id':c.group.id})">
${h.subnav_link(c, h.icon('lock') + _('Authorization'), controller='group', action='authz', id=c.group.name)}
</li><li class="action">
--- a/ckan/templates/home/index.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/home/index.html Wed Sep 21 12:04:00 2011 +0100
@@ -6,108 +6,6 @@
<py:def function="page_title">Welcome</py:def><py:def function="body_class">hide-sidebar</py:def>
- <py:def function="optional_head">
- <style>
- #minornavigation {
- display: none;
- }
-
- #sidebar {
- display: none;
- }
-
- .front-page .action-box h1 {
- padding-top: 0.6em;
- padding-bottom: 0.5em;
- font-size: 2.1em;
- }
-
- .front-page .action-box {
- border-radius: 20px;
- background: #FFF7C0;
- }
-
- .front-page .action-box-inner {
- margin: 20px;
- margin-bottom: 5px;
- min-height: 15em;
- }
- .front-page .action-box-inner.collaborate {
- background:url(/img/collaborate.png) no-repeat right top;
- }
-
- .front-page .action-box-inner.share {
- background:url(/img/share.png) no-repeat right top;
- }
-
- .front-page .action-box-inner.find {
- background:url(/img/find.png) no-repeat right top;
- }
-
- .front-page .action-box-inner a {
- font-weight: bold;
- }
-
- .front-page .action-box-inner input {
- font-family: 'Ubuntu';
- border-radius: 10px;
- background-color: #fff;
- border: 0px;
- font-size: 1.3em;
- width: 90%;
- border: 1px solid #999;
- color: #666;
- padding: 0.5em;
- }
-
- .front-page .action-box-inner .create-button {
- display: block;
- float: right;
- font-weight: normal;
- font-family: 'Ubuntu';
- margin-top: 1.5em;
- border-radius: 10px;
- background-color: #B22;
- border: 0px;
- font-size: 1.3em;
- color: #fff;
- padding: 0.5em;
- }
-
- .front-page .action-box-inner .create-button:hover {
- background-color: #822;
- }
-
- .front-page .action-box-inner ul {
- margin-top: 1em;
- margin-bottom: 0;
- }
-
- .front-page .whoelse {
- margin-top: 1em;
- }
-
- .front-page .group {
- overflow: hidden;
- }
-
- .front-page .group h3 {
- margin-bottom: 0.5em;
- }
-
- .front-page .group p {
- margin-bottom: 0em;
- min-height: 6em;
- }
-
- .front-page .group strong {
- display: block;
- margin-bottom: 1.5em;
- }
-
- </style>
- </py:def>
-
<div py:match="//div[@id='content']" class="front-page"><div class="span-24 last"><h1>Welcome to ${g.site_title}!</h1>
--- a/ckan/templates/layout_base.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/layout_base.html Wed Sep 21 12:04:00 2011 +0100
@@ -37,7 +37,6 @@
<link rel="stylesheet" href="${g.site_url}/css/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]--><link rel="stylesheet" href="${g.site_url}/css/style.css?v=2" />
- <link rel="stylesheet" href="${g.site_url}/css/forms.css" type="text/css" media="screen, print" /><py:if test="defined('optional_head')">
${optional_head()}
@@ -201,6 +200,7 @@
</footer></div><!-- eo #container -->
+
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script><!--script><![CDATA[window.jQuery || document.write("<script src='${g.site_url}/scripts/vendor/jquery/1.6.2/jquery.js'>\x3C/script>")]]></script--><script type="text/javascript" src="${g.site_url}/scripts/vendor/json2.js"></script>
@@ -223,6 +223,10 @@
<script src="${g.site_url}/scripts/vendor/modernizr/1.7/modernizr.min.js"></script><script type="text/javascript">
+ CKAN.plugins = [
+ // Declare js array from Python string
+ ${['\'%s\', '%s for s in config['ckan.plugins'].split(' ')]}
+ ];
$(document).ready(function() {
var ckan_user = $.cookie("ckan_display_name");
if (ckan_user) {
--- a/ckan/templates/package/edit.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/edit.html Wed Sep 21 12:04:00 2011 +0100
@@ -27,6 +27,11 @@
</li></py:match>
+ <py:match path="cancelbutton">
+ HELLO JEN
+ <input id="cancel" tabindex="100" class="pretty-button" name="cancel" type="reset" action="${h.url_for(controller='package', action='read', id=c.pkg.name)}" value="Cancel" />
+ </py:match>
+
<div py:match="content" class="dataset">
${c.form}
</div>
--- a/ckan/templates/package/edit_form.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/edit_form.html Wed Sep 21 12:04:00 2011 +0100
@@ -25,7 +25,6 @@
</div><div class="submit">
- <input name="preview" type="submit" value="Preview" />
${h.submit('save', _('Save'))}
</div>
--- a/ckan/templates/package/layout.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/layout.html Wed Sep 21 12:04:00 2011 +0100
@@ -8,12 +8,12 @@
<py:match path="minornavigation"><py:if test="c.pkg"><ul class="tabbed">
- <li>${h.subnav_link(c, h.icon('package') + _('View'), controller='package', action='read', id=c.pkg.name)}</li>
- <li py:if="h.check_access('package_update',{'id':c.pkg.id})">
+ <li py:attrs="{'class':'current-tab'} if c.action=='read' else {}">${h.subnav_link(c, h.icon('package') + _('View'), controller='package', action='read', id=c.pkg.name)}</li>
+ <li py:attrs="{'class':'current-tab'} if c.action=='edit' else {}" py:if="h.check_access('package_update',{'id':c.pkg.id})">
${h.subnav_link(c, h.icon('package_edit') + _('Edit'), controller='package', action='edit', id=c.pkg.name)}
</li>
- <li>${h.subnav_link(c, h.icon('page_stack') + _('History'), controller='package', action='history', id=c.pkg.name)}</li>
- <li py:if="h.check_access('package_edit_permissions',{'id':c.pkg.id})">
+ <li py:attrs="{'class':'current-tab'} if c.action=='history' else {}">${h.subnav_link(c, h.icon('page_stack') + _('History'), controller='package', action='history', id=c.pkg.name)}</li>
+ <li py:attrs="{'class':'current-tab'} if c.action=='authz' else {}" py:if="h.check_access('package_edit_permissions',{'id':c.pkg.id})">
${h.subnav_link(c, h.icon('lock') + _('Authorization'), controller='package', action='authz', id=c.pkg.name)}
</li><li class="action">
--- a/ckan/templates/package/new_package_form.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/new_package_form.html Wed Sep 21 12:04:00 2011 +0100
@@ -92,9 +92,9 @@
<thead><tr><th class="resource-expand-link"></th>
- <th class="field_req resource-url">URL*</th>
+ <th class="field_req resource-url">URL</th>
+ <th class="field_opt resource-description">Name</th><th class="field_opt resource-format">Format</th>
- <th class="field_opt resource-description">Description</th><th class="field_opt resource-is-changed"></th></tr></thead>
@@ -108,12 +108,12 @@
<td class="resource-summary resource-url">
${res.get('url', '')}
</td>
+ <td class="resource-summary resource-name">
+ ${res.get('name', '')}
+ </td><td class="resource-summary resource-format">
${res.get('format', '')}
</td>
- <td class="resource-summary resource-description">
- ${res.get('description', '')}
- </td><td class="resource-expanded" colspan="3" style="display: none;"><dl><dt><label class="field_opt">Url</label></dt>
@@ -151,12 +151,11 @@
<div class="resource-add"><ul class="tabs">
- <li>Add a resource:</li>
- <li><a href="#" action="upload-file" class="action-resource-tab">Upload a file</a></li>
+ <li><h4>Add a resource:</h4></li><li><a href="#" action="link-file" class="action-resource-tab">Link to a file</a></li><li><a href="#" action="link-api" class="action-resource-tab">Link to an API</a></li>
+ <li class="upload-file" style="display:none;"><a href="#" action="upload-file" class="action-resource-tab">Upload a file</a></li></ul>
- <div class="resource-add-form"></div></div></fieldset>
@@ -258,11 +257,15 @@
</div><div class="form-submit">
+ <input id="save" tabindex="99" class="pretty-button primary" name="save" type="submit" value="Save Changes" />
+ <py:if test="c.pkg">
+ <input id="cancel" tabindex="100" class="pretty-button href-action" name="cancel" type="reset" value="Cancel" action="${h.url_for(controller='package', action='read', id=c.pkg.name)}" />
+ </py:if><p class="hints"><strong>Important:</strong> By submitting content, you agree to release your contributions
under the <a href="http://opendatacommons.org/licenses/odbl/1.0/">Open Database License</a>. Please <strong>refrain</strong> from editing this page if you are <strong>not</strong> happy to do this.
</p>
- <input id="save" tabindex="99" class="pretty-button primary" name="save" type="submit" value="Save Changes" />
+ <div class="clear"></div></div>
--- a/ckan/templates/package/read_core.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/read_core.html Wed Sep 21 12:04:00 2011 +0100
@@ -14,21 +14,27 @@
<div class="resources subsection"><h3>Resources</h3><table>
- <tr>
- <th>Description</th>
+ <thead>
+ <th>Url</th>
+ <th>Name/Description</th><th>Format</th>
- </tr>
+ </thead><py:for each="res in c.pkg_dict.get('resources', [])"><tr rel="dcat:distribution" resource="_:res${res.id}"
typeof="dcat:Distribution"><td>
+ <a href="${res.get('url', '')}" target="_blank">${res.get('url', '')}</a>
+ </td>
+ <td><py:choose test="">
+ <py:when test="res.get('name')">
+ <span property="rdfs:label">${res.name}</span>
+ </py:when><py:when test="res.get('description')">
- <a href="${res.get('url', '')}" rel="dcat:accessURL" target="_blank"><span
- property="rdfs:label">${res.description}</span></a>
+ <span property="rdfs:label">${res.description}</span></py:when><py:otherwise test="">
- <a href="${res.get('url', '')}" target="_blank">Download <em>(no description)</em></a>
+ <em>(none)</em></py:otherwise></py:choose></td>
--- a/ckan/templates/package/search.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/search.html Wed Sep 21 12:04:00 2011 +0100
@@ -9,15 +9,6 @@
<py:def function="page_title">Search - ${g.site_title}</py:def><py:def function="page_heading">Search - ${g.site_title}</py:def>
- <py:def function="optional_head">
- <style>
- #minornavigation { visibility: hidden; }
- #menusearch {
- display: none;
- }
- </style>
- </py:def>
-
<py:match path="primarysidebar"><li class="widget-container boxed widget_text" py:if="h.check_access('package_create')">
--- a/ckan/templates/package/search_form.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/package/search_form.html Wed Sep 21 12:04:00 2011 +0100
@@ -12,10 +12,6 @@
<input type="hidden" name="${k}" value="${v}" /></py:for></span>
- <!-- Feature disabled for a cleaner page. TODO Remove entirely from backend? -->
- <div style="display: none;" class="dataset-search-filters">Filter by <label for="open_only" class="inline">${h.checkbox(name='open_only', checked=c.open_only)} datasets with open licenses</label>
- <label for="downloadable_only" class="inline">${h.checkbox(name='downloadable_only', checked=c.downloadable_only)} datasets with downloads</label>
- </div><input type="submit" value="${_('Search')}" class="pretty-button primary button" /></form>
--- a/ckan/templates/revision/list.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/revision/list.html Wed Sep 21 12:04:00 2011 +0100
@@ -7,7 +7,7 @@
<py:match path="minornavigation"><ul class="tabbed">
- <li>
+ <li class="current-tab">
${h.subnav_link(c,_('Home'), controller='revision', action='index')}</li><li class="action">
${h.subnav_link(c, h.icon('atom_feed') + _('Subscribe'),
--- a/ckan/templates/user/edit.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/user/edit.html Wed Sep 21 12:04:00 2011 +0100
@@ -9,49 +9,6 @@
</py:def><div py:match="content">
- <a href="#preview" py:if="c.preview">(skip to preview)</a>
-
- <form id="user-edit" action="" method="post" class="simple-form"
- xmlns:py="http://genshi.edgewall.org/"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- >
- <fieldset>
- <legend>Base details</legend>
- <label for="fullname">Full name:</label>
- <input name="fullname" value="${c.user_fullname}" /><br/>
-
- <label for="email">E-Mail:</label>
- <input name="email" value="${c.user_email}" /><br/>
- </fieldset>
- <fieldset>
- <legend>Change your password</legend>
- <label for="password1">Password:</label>
- <input type="password" name="password1" value="" />
- <br/>
- <label for="password2">Password (repeat):</label>
- <input type="password" name="password2" value="" />
- <br/>
- </fieldset>
- <label for="about">About user:</label>
- <textarea id="about" rows="5" name="about" cols="60">${c.user_about}</textarea>
- <p class="small" i18n:msg="">You can use <a href="http://daringfireball.net/projects/markdown/syntax">Markdown formatting</a> here.</p>
-
- <div>
- <input name="preview" type="submit" value="Preview" />
- ${h.submit('save', _('Save'))}
- </div>
- </form>
-
-
- <div id="preview" style="margin-left: 20px;" py:if="c.preview">
- <hr />
- <h2>Preview</h2>
- <h4>Full name: ${c.full_name}</h4>
- <div style="border: 2px dashed red; padding: 5px;">
- ${c.preview}
- </div>
- </div>
-
${Markup(c.form)}
</div>
--- a/ckan/templates/user/edit_user_form.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/user/edit_user_form.html Wed Sep 21 12:04:00 2011 +0100
@@ -19,6 +19,19 @@
<dt><label for="email">E-Mail:</label></dt><dd><input type="text" name="email" value="${data.get('email','')}" /></dd>
+
+ <dt><label for="about">About:</label></dt>
+ <dd class="description-field">
+ <div class="markdown-editor">
+ <ul class="tabs">
+ <li><a href="#" action="write" class="selected">Write</a></li>
+ <li><a href="#" action="preview">Preview</a></li>
+ </ul>
+ <textarea class="markdown-input" tabindex="3" name="about" id="about" placeholder="A little about you...">${data.get('about','')}</textarea>
+ <div class="markdown-preview" style="display: none;"></div>
+ <span class="hints">You can use <a href="http://daringfireball.net/projects/markdown/syntax">Markdown formatting</a> here.</span>
+ </div>
+ </dd></dl></fieldset><fieldset>
@@ -30,13 +43,9 @@
<dd><input type="password" name="password2" value="" /></dd></dl></fieldset>
- <label for="about">About user:</label>
- <textarea id="about" rows="5" name="about" cols="60">${data.get('about','')}</textarea>
- <p class="small" i18n:msg="">You can use <a href="http://daringfireball.net/projects/markdown/syntax">Markdown formatting</a> here.</p>
-
- <div>
- <input name="preview" type="submit" value="Preview" />
- ${h.submit('save', _('Save'))}
+ <div class="form-submit">
+ <input id="save" class="pretty-button primary" name="save" type="submit" value="Save Changes" />
+ <input id="cancel" class="pretty-button href-action" name="cancel" type="reset" value="Cancel" action="${h.url_for(controller='user', action='read')}" /></div></form>
--- a/ckan/templates/user/layout.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/user/layout.html Wed Sep 21 12:04:00 2011 +0100
@@ -5,6 +5,15 @@
py:strip=""
>
+ <py:match path="minornavigation">
+ <ul class="tabbed" py:if="c.is_myself">
+ <li py:attrs="{'class':'current-tab'} if c.action=='read' else {}"><a href="${h.url_for(controller='user', action='read')}">My Profile</a></li>
+ <li py:attrs="{'class':'current-tab'} if c.action=='edit' else {}"><a href="${h.url_for(controller='user', action='edit')}">Edit Profile</a></li>
+ <li><a href="${h.url_for('/user/logout')}">Log out</a></li>
+ </ul>
+ </py:match>
+
+
<xi:include href="../layout.html" /></html>
--- a/ckan/templates/user/read.html Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/templates/user/read.html Wed Sep 21 12:04:00 2011 +0100
@@ -6,13 +6,6 @@
<py:def function="page_heading">${c.user_dict['display_name']}</py:def><py:def function="body_class">user-view</py:def>
- <py:match path="minornavigation">
- <ul class="tabbed" py:if="c.is_myself">
- <li><a href="${h.url_for(controller='user', action='edit')}">Edit your profile</a></li>
- <li><a href="${h.url_for('/user/logout')}">Log out</a></li>
- </ul>
- </py:match>
-
<py:match path="primarysidebar"><li class="widget-container widget_text" py:if="not c.hide_welcome_message"><h3>Activity</h3>
--- a/ckan/tests/functional/api/test_package_search.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/tests/functional/api/test_package_search.py Wed Sep 21 12:04:00 2011 +0100
@@ -49,8 +49,8 @@
# uri parameters
check(UnicodeMultiDict({'q': '', 'ref': 'boris'}),
{"q": "", "ref": "boris"})
- check(UnicodeMultiDict({'filter_by_openness': '1'}),
- {'filter_by_openness': '1'})
+ check(UnicodeMultiDict({}),
+ {})
# uri json
check(UnicodeMultiDict({'qjson': '{"q": "", "ref": "boris"}'}),
{"q": "", "ref": "boris"})
@@ -310,36 +310,6 @@
res_dict = self.data_from_res(res)
assert_equal(res_dict['count'], 3)
- def test_12_filter_by_openness_qjson(self):
- query = {'q': '', 'filter_by_openness': '1'}
- json_query = self.dumps(query)
- offset = self.base_url + '?qjson=%s' % json_query
- res = self.app.get(offset, status=200)
- res_dict = self.data_from_res(res)
- assert_equal(res_dict['count'], 2)
- self.assert_results(res_dict, (u'annakarenina', u'testpkg'))
-
- def test_12_filter_by_openness_q(self):
- offset = self.base_url + '?filter_by_openness=1'
- res = self.app.get(offset, status=200)
- res_dict = self.data_from_res(res)
- assert_equal(res_dict['count'], 2)
- self.assert_results(res_dict, (u'annakarenina', u'testpkg'))
-
- def test_12_filter_by_openness_off_qjson(self):
- query = {'q': '', 'filter_by_openness': '0'}
- json_query = self.dumps(query)
- offset = self.base_url + '?qjson=%s' % json_query
- res = self.app.get(offset, status=200)
- res_dict = self.data_from_res(res)
- assert_equal(res_dict['count'], 3)
-
- def test_12_filter_by_openness_off_q(self):
- offset = self.base_url + '?filter_by_openness=0'
- res = self.app.get(offset, status=200)
- res_dict = self.data_from_res(res)
- assert_equal(res_dict['count'], 3)
-
def test_13_just_groups(self):
offset = self.base_url + '?q=groups:roger'
res = self.app.get(offset, status=200)
--- a/ckan/tests/functional/test_package.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/tests/functional/test_package.py Wed Sep 21 12:04:00 2011 +0100
@@ -338,9 +338,9 @@
res = self.app.get(offset)
assert 'Search - ' in res
self._check_search_results(res, 'annakarenina', ['<strong>1</strong>', 'A Novel By Tolstoy'] )
- self._check_search_results(res, 'warandpeace', ['<strong>0</strong>'], only_downloadable=True )
- self._check_search_results(res, 'warandpeace', ['<strong>0</strong>'], only_open=True )
- self._check_search_results(res, 'annakarenina', ['<strong>1</strong>'], only_open=True, only_downloadable=True )
+ self._check_search_results(res, 'warandpeace', ['<strong>1</strong>'])
+ self._check_search_results(res, 'warandpeace', ['<strong>1</strong>'])
+ self._check_search_results(res, 'annakarenina', ['<strong>1</strong>'])
# check for something that also finds tags ...
self._check_search_results(res, 'russian', ['<strong>2</strong>'])
@@ -362,11 +362,9 @@
# solr's edismax parser won't throw an error, so this should return 0 results
assert '>0<' in results_page, results_page
- def _check_search_results(self, page, terms, requireds, only_open=False, only_downloadable=False):
+ def _check_search_results(self, page, terms, requireds):
form = page.forms['dataset-search']
form['q'] = terms.encode('utf8') # paste doesn't handle this!
- form['open_only'] = only_open
- form['downloadable_only'] = only_downloadable
results_page = form.submit()
assert 'Search - ' in results_page, results_page
results_page = self.main_div(results_page)
--- a/ckan/tests/functional/test_user.py Wed Sep 21 11:02:44 2011 +0100
+++ b/ckan/tests/functional/test_user.py Wed Sep 21 12:04:00 2011 +0100
@@ -482,13 +482,6 @@
fv['about'] = new_about
fv['password1'] = new_password
fv['password2'] = new_password
- res = fv.submit('preview', extra_environ={'REMOTE_USER':username})
-
- # preview
- main_res = self.main_div(res)
- assert 'Edit User: testedit' in main_res, main_res
- in_preview = main_res[main_res.find('Preview'):]
- assert new_about in in_preview, in_preview
# commit
res = fv.submit('save', extra_environ={'REMOTE_USER':username})
@@ -533,14 +526,6 @@
fv['password1'] = ''
fv['password2'] = ''
- res = fv.submit('preview', extra_environ={'REMOTE_USER':username})
-
- # preview
- main_res = self.main_div(res)
- assert 'Edit User: testedit2' in main_res, main_res
- in_preview = main_res[main_res.find('Preview'):]
- assert new_about in in_preview, in_preview
-
# commit
res = fv.submit('save', extra_environ={'REMOTE_USER':username})
assert res.status == 302, self.main_div(res).encode('utf8')
@@ -603,7 +588,6 @@
assert 'Edit User: ' in main_res, main_res
assert 'Test About <a href="http://spamsite.net">spamsite</a>' in main_res, main_res
fv = res.forms['user-edit']
- res = fv.submit('preview', extra_environ={'REMOTE_USER':username})
# commit
res = fv.submit('save', extra_environ={'REMOTE_USER':username})
assert res.status == 200, res.status
--- a/doc/configuration.rst Wed Sep 21 11:02:44 2011 +0100
+++ b/doc/configuration.rst Wed Sep 21 12:04:00 2011 +0100
@@ -524,3 +524,24 @@
ckan.backup_dir = /var/backups/ckan/
This is a directory where SQL database backups are to be written, assuming a script has been installed to do this.
+
+template_footer_end
+^^^^^^^^^^^^^^^^^^^
+
+HTML content to be inserted just before </body> tag (e.g. google analytics code).
+
+.. note:: can use html e.g. <strong>blah</strong> and can have multiline strings (just indent following lines)
+
+Example (showing insertion of google analytics code)::
+
+ ckan.template_footer_end = <!-- Google Analytics -->
+ <script src='http://www.google-analytics.com/ga.js' type='text/javascript'></script>
+ <script type="text/javascript">
+ try {
+ var pageTracker = _gat._getTracker("XXXXXXXXX");
+ pageTracker._setDomainName(".ckan.net");
+ pageTracker._trackPageview();
+ } catch(err) {}
+ </script>
+ <!-- /Google Analytics -->
+
--- a/doc/theming.rst Wed Sep 21 11:02:44 2011 +0100
+++ b/doc/theming.rst Wed Sep 21 12:04:00 2011 +0100
@@ -69,16 +69,20 @@
Next, copy the ``layout.html`` template and add a reference to the new CSS file. Here is an example of the edited ``layout.html`` template::
- <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="">
- <py:def function="optional_head">
- <link rel="stylesheet" href="${g.site_url}/css/mycss.css" />
- </py:def>
- <xi:include href="layout_base.html" />
- </html>
+ <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="">
+
+ <head py:match="head">
+ ${select('*')}
+
+ <link rel="stylesheet" href="${g.site_url}/css/mycss.css" />
+ </head>
+
+ <xi:include href="layout_base.html" />
+ </html>
Retheming the Site with Templates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -98,4 +102,4 @@
.. note::
- For more information on the syntax of the CKAN templates, refer to the `Genshi documentation <http://genshi.edgewall.org/wiki/Documentation>`_.
\ No newline at end of file
+ For more information on the syntax of the CKAN templates, refer to the `Genshi documentation <http://genshi.edgewall.org/wiki/Documentation>`_.
Repository URL: https://bitbucket.org/okfn/ckan/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the ckan-changes
mailing list