Merge pull request #5 from wildcatzita/master
Added more features. Fixed bug with rating shown
This commit is contained in:
commit
6a94f97837
30
README.rst
30
README.rst
|
@ -2,12 +2,12 @@
|
||||||
CKAN Rating extension
|
CKAN Rating extension
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is a simple rating extension for CKAN datasets (packages) and showcases. The extension adds a list of clickable stars to the side navigation
|
This is a simple rating extension for CKAN datasets (packages) and showcases. The extension adds a list of clickable stars to the side navigation
|
||||||
in the dataset and showcacse templates similar to ckanext-qa. In showcase the stars are also displayed in the showcase listing, but are not clickable.
|
in the dataset and showcacse templates similar to ckanext-qa. In showcase the stars are also displayed in the showcase listing, but are not clickable.
|
||||||
|
|
||||||
The stars can also be added to any desired view by adding the following code to the desired template::
|
The stars can also be added to any desired view by adding the following code to the desired template::
|
||||||
|
|
||||||
{% snippet "rating/stars.html", package=<YOUR_PACKAGE> %}
|
{% snippet "rating/snippets/stars.html", package=<YOUR_PACKAGE> %}
|
||||||
|
|
||||||
The amount of ratings submitted can also be displayed with::
|
The amount of ratings submitted can also be displayed with::
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Rating is identified with client IP if the user is not authenticated. User ID is
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
This extension works with CKAN version 2.5 or later.
|
This extension works with CKAN version 2.5 or later.
|
||||||
|
|
||||||
|
|
||||||
------------
|
------------
|
||||||
|
@ -51,6 +51,20 @@ To install ckanext-rating:
|
||||||
6. If you want to use this extension for ckanext-showcase, install it into your environment by following the instructions at https://github.com/ckan/ckanext-showcase
|
6. If you want to use this extension for ckanext-showcase, install it into your environment by following the instructions at https://github.com/ckan/ckanext-showcase
|
||||||
|
|
||||||
|
|
||||||
|
---------------
|
||||||
|
Config Settings
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Rating is enabled or disabled for unauthenticated users::
|
||||||
|
|
||||||
|
rating.enabled_for_unauthenticated_users = true or false
|
||||||
|
|
||||||
|
Optional::
|
||||||
|
|
||||||
|
# List of dataset types for which the rating will be shown (defaults to ['dataset'])
|
||||||
|
ckanext.rating.enabled_dataset_types
|
||||||
|
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
Development Installation
|
Development Installation
|
||||||
------------------------
|
------------------------
|
||||||
|
@ -62,13 +76,3 @@ do::
|
||||||
cd ckanext-rating
|
cd ckanext-rating
|
||||||
python setup.py develop
|
python setup.py develop
|
||||||
pip install -r dev-requirements.txt
|
pip install -r dev-requirements.txt
|
||||||
|
|
||||||
|
|
||||||
---------------
|
|
||||||
Config Settings
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Optional::
|
|
||||||
|
|
||||||
# List of dataset types for which the rating will be shown (defaults to ['dataset'])
|
|
||||||
ckanext.rating.enabled_dataset_types
|
|
||||||
|
|
|
@ -2,45 +2,56 @@ import ckan.plugins as p
|
||||||
import ckan.model as model
|
import ckan.model as model
|
||||||
import ckan.logic as logic
|
import ckan.logic as logic
|
||||||
from ckan.lib.base import h
|
from ckan.lib.base import h
|
||||||
|
from ckan.controllers.package import PackageController
|
||||||
|
from ckan.common import request
|
||||||
|
|
||||||
c = p.toolkit.c
|
c = p.toolkit.c
|
||||||
flatten_to_string_key = logic.flatten_to_string_key
|
flatten_to_string_key = logic.flatten_to_string_key
|
||||||
|
|
||||||
|
|
||||||
class RatingController(p.toolkit.BaseController):
|
class RatingController(p.toolkit.BaseController):
|
||||||
|
|
||||||
def submit_package_rating(self, package, rating):
|
def submit_package_rating(self, package, rating):
|
||||||
p.toolkit.get_action('rating_package_create')(
|
context = {'model': model, 'user': c.user or c.author}
|
||||||
context = {'model': model,
|
data_dict = {'package': package, 'rating': rating}
|
||||||
'user': c.user or c.author},
|
if p.toolkit.check_access('check_access_user', context, data_dict):
|
||||||
data_dict={'package': package,
|
p.toolkit.get_action('rating_package_create')(context, data_dict)
|
||||||
'rating': rating}
|
h.redirect_to(str('/dataset/' + package))
|
||||||
)
|
return p.toolkit.render('package/read.html')
|
||||||
h.redirect_to(str('/dataset/' + package))
|
|
||||||
return p.toolkit.render('package/read.html')
|
|
||||||
|
|
||||||
def submit_showcase_rating(self, package, rating):
|
def submit_showcase_rating(self, package, rating):
|
||||||
p.toolkit.get_action('rating_package_create')(
|
context = {'model': model, 'user': c.user or c.author}
|
||||||
context = {'model': model,
|
data_dict = {'package': package, 'rating': rating}
|
||||||
'user': c.user or c.author},
|
if p.toolkit.check_access('check_access_user', context, data_dict):
|
||||||
data_dict={'package': package,
|
p.toolkit.get_action('rating_package_create')(context, data_dict)
|
||||||
'rating': rating}
|
h.redirect_to(str('/showcase/' + package))
|
||||||
)
|
return p.toolkit.render('showcase/showcase_info.html')
|
||||||
h.redirect_to(str('/showcase/' + package))
|
|
||||||
return p.toolkit.render('showcase/showcase_info.html')
|
|
||||||
|
|
||||||
def submit_ajax_package_rating(self, package, rating):
|
def submit_ajax_package_rating(self, package, rating):
|
||||||
try:
|
context = {'model': model, 'user': c.user or c.author}
|
||||||
p.toolkit.get_action('rating_package_create')(
|
data_dict = {'package': package, 'rating': rating}
|
||||||
context = {'model': model,
|
if p.toolkit.check_access('check_access_user', context, data_dict):
|
||||||
'user': c.user or c.author},
|
try:
|
||||||
data_dict={'package': package,
|
p.toolkit.get_action('rating_package_create')(
|
||||||
'rating': rating}
|
context, data_dict)
|
||||||
)
|
except Exception, ex:
|
||||||
except Exception, ex:
|
errors = ex
|
||||||
errors = ex
|
else:
|
||||||
else:
|
data['success'] = True
|
||||||
data['success'] = True
|
|
||||||
|
|
||||||
data = flatten_to_string_key({ 'data': data, 'errors': errors }),
|
data = flatten_to_string_key({'data': data, 'errors': errors}),
|
||||||
response.headers['Content-Type'] = 'application/json;charset=utf-8'
|
response.headers['Content-Type'] = 'application/json;charset=utf-8'
|
||||||
return h.json.dumps(data)
|
return h.json.dumps(data)
|
||||||
|
|
||||||
|
|
||||||
|
class RatingPackageController(PackageController):
|
||||||
|
|
||||||
|
def search(self):
|
||||||
|
cur_page = request.params.get('page')
|
||||||
|
if cur_page is not None:
|
||||||
|
c.current_page = self._get_page_number(request.params)
|
||||||
|
else:
|
||||||
|
c.current_page = 1
|
||||||
|
c.pkg_type = 'dataset'
|
||||||
|
result = super(RatingPackageController, self).search()
|
||||||
|
return result
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
from ckanext.rating.model import Rating
|
from ckanext.rating.model import Rating
|
||||||
from ckan.plugins import toolkit
|
from ckan.plugins import toolkit
|
||||||
from pylons import config
|
from pylons import config
|
||||||
import ckan.model as model
|
|
||||||
|
|
||||||
c = toolkit.c
|
c = toolkit.c
|
||||||
|
|
||||||
|
|
||||||
def get_user_rating(package_id):
|
def get_user_rating(package_id):
|
||||||
context = {'model': model, 'user': c.user}
|
if not c.userobj:
|
||||||
|
|
||||||
from ckan.model import User
|
|
||||||
if not isinstance(context.get('user'), User):
|
|
||||||
user = toolkit.request.environ.get('REMOTE_ADDR')
|
user = toolkit.request.environ.get('REMOTE_ADDR')
|
||||||
|
else:
|
||||||
|
user = c.userobj
|
||||||
user_rating = Rating.get_user_package_rating(user, package_id).first()
|
user_rating = Rating.get_user_package_rating(user, package_id).first()
|
||||||
return user_rating.rating if user_rating is not None else None
|
return user_rating.rating if user_rating is not None else None
|
||||||
|
|
||||||
|
|
||||||
def show_rating_in_type(type):
|
def show_rating_in_type(type):
|
||||||
return type in config.get('ckanext.rating.enabled_dataset_types', ['dataset'])
|
return type in config.get('ckanext.rating.enabled_dataset_types',
|
||||||
|
['dataset'])
|
||||||
|
|
|
@ -6,6 +6,7 @@ from ckan.plugins import toolkit
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def rating_package_create(context, data_dict):
|
def rating_package_create(context, data_dict):
|
||||||
'''Review a dataset (package).
|
'''Review a dataset (package).
|
||||||
:param package: the name or id of the dataset to rate
|
:param package: the name or id of the dataset to rate
|
||||||
|
@ -27,7 +28,7 @@ def rating_package_create(context, data_dict):
|
||||||
error = None
|
error = None
|
||||||
if not package_ref:
|
if not package_ref:
|
||||||
error = _('You must supply a package id or name '
|
error = _('You must supply a package id or name '
|
||||||
'(parameter "package").')
|
'(parameter "package").')
|
||||||
elif not rating:
|
elif not rating:
|
||||||
error = _('You must supply a rating (parameter "rating").')
|
error = _('You must supply a rating (parameter "rating").')
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
from .create import rating_create_auth
|
||||||
|
|
||||||
|
|
||||||
|
def get_rating_auth_dict():
|
||||||
|
rating_auth = dict()
|
||||||
|
rating_auth.update(rating_create_auth())
|
||||||
|
return rating_auth
|
|
@ -0,0 +1,20 @@
|
||||||
|
import pylons.config as config
|
||||||
|
from ckan.plugins import toolkit
|
||||||
|
import ckan.logic as logic
|
||||||
|
c = toolkit.c
|
||||||
|
|
||||||
|
|
||||||
|
def rating_create_auth():
|
||||||
|
return {
|
||||||
|
'check_access_user': check_access_user,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@logic.auth_allow_anonymous_access
|
||||||
|
def check_access_user(context, data_dict):
|
||||||
|
if c.user:
|
||||||
|
return {'success': True}
|
||||||
|
else:
|
||||||
|
allow_rating = toolkit.asbool(
|
||||||
|
config.get('rating.enabled_for_unauthenticated_users', True))
|
||||||
|
return {'success': allow_rating}
|
|
@ -16,9 +16,11 @@ __all__ = ['MIN_RATING', 'MAX_RATING']
|
||||||
MIN_RATING = 1.0
|
MIN_RATING = 1.0
|
||||||
MAX_RATING = 5.0
|
MAX_RATING = 5.0
|
||||||
|
|
||||||
|
|
||||||
def make_uuid():
|
def make_uuid():
|
||||||
return unicode(uuid.uuid4())
|
return unicode(uuid.uuid4())
|
||||||
|
|
||||||
|
|
||||||
class Rating(Base):
|
class Rating(Base):
|
||||||
|
|
||||||
__tablename__ = 'review'
|
__tablename__ = 'review'
|
||||||
|
@ -43,7 +45,7 @@ class Rating(Base):
|
||||||
existing_rating = cls.get_user_package_rating(ip_or_user, package_id)
|
existing_rating = cls.get_user_package_rating(ip_or_user, package_id)
|
||||||
|
|
||||||
if (existing_rating.first()):
|
if (existing_rating.first()):
|
||||||
existing_rating.update({ 'rating': rating })
|
existing_rating.update({'rating': rating})
|
||||||
model.repo.commit()
|
model.repo.commit()
|
||||||
log.info('Review updated for package')
|
log.info('Review updated for package')
|
||||||
else:
|
else:
|
||||||
|
@ -55,10 +57,10 @@ class Rating(Base):
|
||||||
ip_or_user = None
|
ip_or_user = None
|
||||||
|
|
||||||
review = Rating(
|
review = Rating(
|
||||||
user_id = user_id,
|
user_id=user_id,
|
||||||
rater_ip = ip_or_user,
|
rater_ip=ip_or_user,
|
||||||
package_id = package_id,
|
package_id=package_id,
|
||||||
rating = rating
|
rating=rating
|
||||||
)
|
)
|
||||||
|
|
||||||
model.Session.add(review)
|
model.Session.add(review)
|
||||||
|
@ -71,7 +73,8 @@ class Rating(Base):
|
||||||
.filter(cls.package_id == package_id) \
|
.filter(cls.package_id == package_id) \
|
||||||
.all()
|
.all()
|
||||||
|
|
||||||
average = sum(r.rating for r in ratings) / float(len(ratings)) if len(ratings) > 0 else 0
|
average = sum(r.rating for r in ratings) / float(len(ratings)) if (
|
||||||
|
len(ratings) > 0) else 0
|
||||||
return {
|
return {
|
||||||
'rating': round(average, 2),
|
'rating': round(average, 2),
|
||||||
'ratings_count': len(ratings)
|
'ratings_count': len(ratings)
|
||||||
|
@ -87,11 +90,14 @@ class Rating(Base):
|
||||||
user_id = ip_or_user.id
|
user_id = ip_or_user.id
|
||||||
ip_or_user = None
|
ip_or_user = None
|
||||||
|
|
||||||
rating = model.Session.query(cls) \
|
rating = model.Session.query(cls).filter(
|
||||||
.filter(cls.package_id == package_id, cls.user_id == user_id, cls.rater_ip == ip_or_user)
|
cls.package_id == package_id,
|
||||||
|
cls.user_id == user_id,
|
||||||
|
cls.rater_ip == ip_or_user)
|
||||||
|
|
||||||
return rating
|
return rating
|
||||||
|
|
||||||
|
|
||||||
def init_tables(engine):
|
def init_tables(engine):
|
||||||
Base.metadata.create_all(engine)
|
Base.metadata.create_all(engine)
|
||||||
log.info('Rating database tables are set-up')
|
log.info('Rating database tables are set-up')
|
||||||
|
|
|
@ -1,12 +1,57 @@
|
||||||
import ckan.plugins as plugins
|
import ckan.plugins as plugins
|
||||||
import ckan.plugins.toolkit as toolkit
|
import ckan.plugins.toolkit as toolkit
|
||||||
|
from ckan.common import request, c, g
|
||||||
|
import sqlalchemy
|
||||||
|
import ckan.model as model
|
||||||
|
|
||||||
from ckanext.rating.logic import action
|
from ckanext.rating.logic import action
|
||||||
from ckanext.rating import helpers
|
from ckanext.rating import helpers
|
||||||
|
import ckanext.rating.logic.auth as rating_auth
|
||||||
|
from ckanext.rating.model import Rating
|
||||||
|
|
||||||
|
|
||||||
|
def sort_by_rating(sort):
|
||||||
|
limit = g.datasets_per_page
|
||||||
|
if c.current_page:
|
||||||
|
page = c.current_page
|
||||||
|
else:
|
||||||
|
page = 1
|
||||||
|
offset = (page - 1) * limit
|
||||||
|
c.count_pkg = model.Session.query(
|
||||||
|
sqlalchemy.func.count(model.Package.id)).\
|
||||||
|
filter(model.Package.type == 'dataset').\
|
||||||
|
filter(model.Package.private == False).\
|
||||||
|
filter(model.Package.state == 'active').scalar()
|
||||||
|
query = model.Session.query(
|
||||||
|
model.Package.id, model.Package.title,
|
||||||
|
sqlalchemy.func.avg(
|
||||||
|
sqlalchemy.func.coalesce(Rating.rating, 0)).
|
||||||
|
label('rating_avg')).\
|
||||||
|
outerjoin(Rating, Rating.package_id == model.Package.id).\
|
||||||
|
filter(model.Package.type == 'dataset').\
|
||||||
|
filter(model.Package.private == False).\
|
||||||
|
filter(model.Package.state == 'active').\
|
||||||
|
group_by(model.Package.id).\
|
||||||
|
distinct()
|
||||||
|
if sort == 'rating desc':
|
||||||
|
query = query.order_by(sqlalchemy.desc('rating_avg'))
|
||||||
|
else:
|
||||||
|
query = query.order_by(sqlalchemy.asc('rating_avg'))
|
||||||
|
res = query.offset(offset).limit(limit)
|
||||||
|
c.qr = q = [id[0] for id in res]
|
||||||
|
tmp = 'id:('
|
||||||
|
for id in q:
|
||||||
|
tmp += id + ' OR '
|
||||||
|
q = tmp[:-4] + ')'
|
||||||
|
return q
|
||||||
|
|
||||||
|
|
||||||
class RatingPlugin(plugins.SingletonPlugin):
|
class RatingPlugin(plugins.SingletonPlugin):
|
||||||
plugins.implements(plugins.IConfigurer)
|
plugins.implements(plugins.IConfigurer)
|
||||||
plugins.implements(plugins.IActions)
|
plugins.implements(plugins.IActions)
|
||||||
plugins.implements(plugins.ITemplateHelpers)
|
plugins.implements(plugins.ITemplateHelpers)
|
||||||
|
plugins.implements(plugins.IAuthFunctions)
|
||||||
|
plugins.implements(plugins.IPackageController, inherit=True)
|
||||||
plugins.implements(plugins.IRoutes, inherit=True)
|
plugins.implements(plugins.IRoutes, inherit=True)
|
||||||
|
|
||||||
# IConfigurer
|
# IConfigurer
|
||||||
|
@ -21,14 +66,14 @@ class RatingPlugin(plugins.SingletonPlugin):
|
||||||
# IActions
|
# IActions
|
||||||
|
|
||||||
def get_actions(self):
|
def get_actions(self):
|
||||||
return {
|
return {
|
||||||
'rating_package_create': action.rating_package_create,
|
'rating_package_create': action.rating_package_create,
|
||||||
'rating_package_get': action.rating_package_get,
|
'rating_package_get': action.rating_package_get,
|
||||||
'rating_showcase_create': action.rating_package_create,
|
'rating_showcase_create': action.rating_package_create,
|
||||||
'rating_showcase_get': action.rating_package_get
|
'rating_showcase_get': action.rating_package_get
|
||||||
}
|
}
|
||||||
|
|
||||||
## ITemplateHelpers
|
# ITemplateHelpers
|
||||||
|
|
||||||
def get_helpers(self):
|
def get_helpers(self):
|
||||||
return {
|
return {
|
||||||
|
@ -37,6 +82,32 @@ class RatingPlugin(plugins.SingletonPlugin):
|
||||||
'show_rating_in_type': helpers.show_rating_in_type
|
'show_rating_in_type': helpers.show_rating_in_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# IAuthFunctions
|
||||||
|
|
||||||
|
def get_auth_functions(self):
|
||||||
|
return rating_auth.get_rating_auth_dict()
|
||||||
|
|
||||||
|
# IPackageController
|
||||||
|
|
||||||
|
def before_search(self, search_params):
|
||||||
|
sort = request.params.get('sort', '')
|
||||||
|
if sort in ['rating desc', 'rating asc']:
|
||||||
|
search_params['q'] = sort_by_rating(sort)
|
||||||
|
search_params['start'] = 0
|
||||||
|
return search_params
|
||||||
|
|
||||||
|
def after_search(self, search_results, search_params):
|
||||||
|
sort = search_params.get('sort', '')
|
||||||
|
if sort in ['rating desc', 'rating asc']:
|
||||||
|
tmp = []
|
||||||
|
for id in c.qr:
|
||||||
|
for pkg in search_results['results']:
|
||||||
|
if id == pkg['id']:
|
||||||
|
tmp.append(pkg)
|
||||||
|
search_results['results'] = tmp
|
||||||
|
search_results['count'] = c.count_pkg
|
||||||
|
return search_results
|
||||||
|
|
||||||
# IRoutes
|
# IRoutes
|
||||||
|
|
||||||
def before_map(self, map):
|
def before_map(self, map):
|
||||||
|
@ -48,4 +119,11 @@ class RatingPlugin(plugins.SingletonPlugin):
|
||||||
controller='ckanext.rating.controller:RatingController',
|
controller='ckanext.rating.controller:RatingController',
|
||||||
action='submit_showcase_rating')
|
action='submit_showcase_rating')
|
||||||
|
|
||||||
return map
|
map.connect(
|
||||||
|
'/dataset',
|
||||||
|
controller='ckanext.rating.controller:RatingPackageController',
|
||||||
|
action='search',
|
||||||
|
highlight_actions='index search'
|
||||||
|
)
|
||||||
|
|
||||||
|
return map
|
||||||
|
|
|
@ -22,4 +22,13 @@ a.rating-star-hover:hover {
|
||||||
.rating-description {
|
.rating-description {
|
||||||
color: #7c7c82;
|
color: #7c7c82;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataset-raiting {
|
||||||
|
float: right;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-raiting span {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{% ckan_extends %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
{% set facets = {
|
||||||
|
'fields': c.fields_grouped,
|
||||||
|
'search': c.search_facets,
|
||||||
|
'titles': c.facet_titles,
|
||||||
|
'translated_fields': c.translated_fields,
|
||||||
|
'remove_field': c.remove_field }
|
||||||
|
%}
|
||||||
|
{% set sorting = [
|
||||||
|
(_('Relevance'), 'score desc, metadata_modified desc'),
|
||||||
|
(_('Name Ascending'), 'title_string asc'),
|
||||||
|
(_('Name Descending'), 'title_string desc'),
|
||||||
|
(_('Rating Ascending'), 'rating asc') if h.show_rating_in_type(c.pkg_type) else (false, false),
|
||||||
|
(_('Rating Descending'), 'rating desc') if h.show_rating_in_type(c.pkg_type) else (false, false),
|
||||||
|
(_('Last Modified'), 'metadata_modified desc'),
|
||||||
|
(_('Popular'), 'views_recent desc') if g.tracking_enabled else (false, false) ]
|
||||||
|
%}
|
||||||
|
{% snippet 'snippets/search_form.html', form_id='dataset-search-form', type='dataset', query=c.q, sorting=sorting, sorting_selected=c.sort_by_selected, count=c.page.item_count, facets=facets, show_empty=request.params, error=c.query_error, fields=c.fields %}
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{% ckan_extends %}
|
||||||
|
|
||||||
|
{% block package_info %}
|
||||||
|
{% if pkg %}
|
||||||
|
<section class="module module-narrow">
|
||||||
|
<div class="module context-info">
|
||||||
|
<div class="module-content">
|
||||||
|
{% block package_info_inner %}
|
||||||
|
{{ super() }}
|
||||||
|
{% endblock %}
|
||||||
|
{% snippet "rating/snippets/rating.html", package=pkg %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
|
@ -1,27 +1,35 @@
|
||||||
{#
|
{#
|
||||||
Renders a complete block of rating snippets with an option to rate the dataset
|
Renders a complete block of rating snippets
|
||||||
|
|
||||||
package - The package for which the rating is displayed
|
package - The package for which the rating is displayed
|
||||||
|
|
||||||
{% snippet "rating/snippets/rating.html", package=pkg %}
|
{% snippet "rating/snippets/rating.html", package=pkg %}
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
{% resource "rating_css/rating.css" %}
|
||||||
{% if h.show_rating_in_type(package.type) %}
|
{% if h.show_rating_in_type(package.type) %}
|
||||||
<div class="rating">
|
<div class="rating">
|
||||||
{% block general_rating %}
|
{% block general_rating %}
|
||||||
<h2 class="heading">{{ _('Rating') }}</h2>
|
<h2 class="heading">{{ _('Rating') }}</h2>
|
||||||
<div class="rating-container">
|
<div class="rating-container">
|
||||||
{% snippet "rating/snippets/stars_inactive.html", package=package %}
|
{% snippet "rating/snippets/stars_inactive.html", package=package %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block user_rating %}
|
{% block user_rating %}
|
||||||
<h2 class="heading">{{ _('Your rating') }}</h2>
|
{% if h.check_access('check_access_user') %}
|
||||||
<div class="rating-container">
|
<h2 class="heading">{{ _('Your rating') }}</h2>
|
||||||
{%- snippet "rating/snippets/stars.html", package=package -%}<br>
|
<div class="rating-container">
|
||||||
<span class="rating-details">
|
{%- snippet "rating/snippets/stars.html", package=package -%}
|
||||||
{%- snippet "rating/snippets/rating_description.html", rating=h.get_user_rating(package.id) -%}
|
{% block user_rating_br %}<br>{% endblock %}
|
||||||
</span>
|
<span class="rating-details">
|
||||||
</div>
|
{%- snippet "rating/snippets/rating_description.html", rating=h.get_user_rating(package.id) -%}
|
||||||
{% endblock %}
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% else %}
|
||||||
|
<div class="login-rating-details">
|
||||||
|
<a href="{{ h.url_for('login') }}">{{ _('Login') }}</a> {{ _('to leave a rating') }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{#
|
{#
|
||||||
Renders a set of stars which are not clickable
|
Renders a set of stars
|
||||||
|
|
||||||
stars - The number of stars to be displayed.
|
stars - The number of stars to be displayed.
|
||||||
|
|
||||||
|
@ -9,18 +9,32 @@ stars - The number of stars to be displayed.
|
||||||
|
|
||||||
{% set ratings_count = h.package_rating(None, {'package_id' : package.id} ).ratings_count%}
|
{% set ratings_count = h.package_rating(None, {'package_id' : package.id} ).ratings_count%}
|
||||||
{% set stars = h.package_rating(None, {'package_id' : package.id} ).rating %}
|
{% set stars = h.package_rating(None, {'package_id' : package.id} ).rating %}
|
||||||
<span class="star-rating{% if stars == 0 %} no-stars{% endif %}">
|
{% if stars|int < stars %}
|
||||||
<span class="star-rating-stars">
|
{% set half_star = 1 %}
|
||||||
{%- for index in range(stars|int) -%}
|
{% else %}
|
||||||
<span class="icon icon-star rating-star"></span>
|
{% set half_star = 0 %}
|
||||||
{%- endfor -%}
|
{% endif %}
|
||||||
{%- for index in range(stars|int, 5) -%}
|
|
||||||
<span class="icon icon-star-empty rating-star"></span>
|
|
||||||
{%- endfor -%}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<br>
|
|
||||||
<span class="rating-description">
|
|
||||||
{{ ratings_count }} {{ _('rating') if ratings_count == 1 else _('ratings') }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
{% block main_star_rating %}
|
||||||
|
<span class="star-rating{% if stars == 0 %} no-stars{% endif %}">
|
||||||
|
<span class="star-rating-stars">
|
||||||
|
{%- for index in range(stars|int) -%}
|
||||||
|
<span class="icon icon-star"></span>
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if half_star == 1 -%}
|
||||||
|
<span class="icon icon-star-half-empty"></span>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- for index in range(stars|int + half_star, 5) -%}
|
||||||
|
<span class="icon icon-star-empty"></span>
|
||||||
|
{%- endfor -%}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main_star_rating_br %}
|
||||||
|
<br>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block star_rating_description %}
|
||||||
|
<span class="rating-description">{{ ratings_count }} {{ _('rating') if ratings_count == 1 else _('ratings') }}</span>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{% resource "rating_css/rating.css" %}
|
||||||
|
|
||||||
|
{% ckan_extends %}
|
||||||
|
|
||||||
|
{% block heading_title %}
|
||||||
|
{{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }}
|
||||||
|
{% set rating = h.package_rating(None, {'package_id' : package.id} ).rating|float %}
|
||||||
|
{% if rating != 0 %}
|
||||||
|
<div class="dataset-raiting">
|
||||||
|
<span>{{rating|round(1)}}</span>
|
||||||
|
<i class="user-rating-star icon icon-star"></i>
|
||||||
|
</div>
|
||||||
|
{% endif%}
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue