Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added filters for plugin views, added stars in listing

  • Loading branch information...
commit 2419a0284a679ce3a0f0657f1a5bc1d7c7113748 1 parent 239535a
Alessandro Pasotti elpaso authored
12 qgis-app/plugins/api.py
... ... @@ -1,3 +1,7 @@
  1 +"""
  2 +XML-RPC webservices for the plugin web application
  3 +"""
  4 +
1 5 from rpc4django import rpcmethod
2 6 from xmlrpclib import Fault
3 7 from plugins.models import *
@@ -103,7 +107,6 @@ def plugin_upload(package, **kwargs):
103 107 def plugin_tags(**kwargs):
104 108 """
105 109 Returns a list of current tags, in alphabetical order
106   -
107 110 """
108 111 return [t.name for t in Tag.objects.all().order_by('name')]
109 112
@@ -111,7 +114,7 @@ def plugin_tags(**kwargs):
111 114 @rpcmethod(name='plugin.vote', signature=['array', 'integer', 'integer'], login_required=False)
112 115 def plugin_tags(plugin_id, vote, **kwargs):
113 116 """
114   - Vote a plugin
  117 + Vote a plugin, valid values are 1-5
115 118 """
116 119 try:
117 120 request = kwargs.get('request')
@@ -121,11 +124,10 @@ def plugin_tags(plugin_id, vote, **kwargs):
121 124 try:
122 125 plugin = Plugin.objects.get(pk=plugin_id)
123 126 except Plugin.DoesNotExist:
124   - msg = unicode(_('Plugin with id %s does not exists') % plugin_id)
  127 + msg = unicode(_('Plugin with id %s does not exists.') % plugin_id)
125 128 raise ValidationError(msg)
126 129 if not int(vote) in range(1, 6):
127   - msg = unicode(_('%s is not a valid vote (1-5)') % vote)
  130 + msg = unicode(_('%s is not a valid vote (1-5).') % vote)
128 131 raise ValidationError(msg)
129 132 return [plugin.rating.add(score=int(vote), user=request.user, ip_address=request.META['REMOTE_ADDR'])]
130 133
131   -
58 qgis-app/plugins/models.py
@@ -16,7 +16,17 @@
16 16 PLUGINS_STORAGE_PATH = getattr(settings, 'PLUGINS_STORAGE_PATH', 'packages')
17 17 PLUGINS_FRESH_DAYS = getattr(settings, 'PLUGINS_FRESH_DAYS', 30)
18 18
19   -class ApprovedPlugins(models.Manager):
  19 +class BasePluginManager(models.Manager):
  20 + """
  21 + Adds a score
  22 + """
  23 + def get_query_set(self):
  24 + return super(BasePluginManager, self).get_query_set().extra(
  25 + select={
  26 + 'average_vote': 'rating_score/(rating_votes+0.001)'
  27 + })
  28 +
  29 +class ApprovedPlugins(BasePluginManager):
20 30 """
21 31 Shows only public plugins: i.e. those with
22 32 and with at least one approved version ("stable" or "experimental")
@@ -25,7 +35,7 @@ def get_query_set(self):
25 35 return super(ApprovedPlugins, self).get_query_set().filter(pluginversion__approved=True).distinct()
26 36
27 37
28   -class StablePlugins(models.Manager):
  38 +class StablePlugins(BasePluginManager):
29 39 """
30 40 Shows only public plugins: i.e. those with "approved" flag set
31 41 and with one "stable" version
@@ -34,7 +44,7 @@ def get_query_set(self):
34 44 return super(StablePlugins, self).get_query_set().filter(pluginversion__approved=True, pluginversion__experimental=False).distinct()
35 45
36 46
37   -class ExperimentalPlugins(models.Manager):
  47 +class ExperimentalPlugins(BasePluginManager):
38 48 """
39 49 Shows only public plugins: i.e. those with "approved" flag set
40 50 and with one "experimental" version
@@ -43,7 +53,7 @@ def get_query_set(self):
43 53 return super(ExperimentalPlugins, self).get_query_set().filter(pluginversion__approved=True, pluginversion__experimental=True).distinct()
44 54
45 55
46   -class FeaturedPlugins(models.Manager):
  56 +class FeaturedPlugins(BasePluginManager):
47 57 """
48 58 Shows only public featured stable plugins: i.e. those with "approved" flag set
49 59 and "featured" flag set
@@ -52,7 +62,7 @@ def get_query_set(self):
52 62 return super(FeaturedPlugins, self).get_query_set().filter(pluginversion__approved=True, featured=True).order_by('-created_on').distinct()
53 63
54 64
55   -class FreshPlugins(models.Manager):
  65 +class FreshPlugins(BasePluginManager):
56 66 """
57 67 Shows only approved plugins: i.e. those with "approved" version flag set
58 68 and modified less than "days" ago.
@@ -66,7 +76,7 @@ def get_query_set(self):
66 76 return super(FreshPlugins, self).get_query_set().filter(pluginversion__approved=True, modified_on__gte = datetime.datetime.now()- datetime.timedelta(days = self.days)).order_by('-created_on').distinct()
67 77
68 78
69   -class UnapprovedPlugins(models.Manager):
  79 +class UnapprovedPlugins(BasePluginManager):
70 80 """
71 81 Shows only unapproved plugins
72 82 """
@@ -74,7 +84,7 @@ def get_query_set(self):
74 84 return super(UnapprovedPlugins, self).get_query_set().filter(pluginversion__approved=False).distinct()
75 85
76 86
77   -class DeprecatedPlugins(models.Manager):
  87 +class DeprecatedPlugins(BasePluginManager):
78 88 """
79 89 Shows only deprecated plugins
80 90 """
@@ -82,19 +92,44 @@ def get_query_set(self):
82 92 return super(DeprecatedPlugins, self).get_query_set().filter(deprecated=True).distinct()
83 93
84 94
  95 +
85 96 class PopularPlugins(ApprovedPlugins):
86 97 """
87   - Shows only unapproved plugins, sort by downloads
  98 + Shows only approved plugins, sort by popularity algorithm
88 99 """
89 100 def get_query_set(self):
90 101 return super(PopularPlugins, self).get_query_set().filter(deprecated=False).extra(
91 102 select={
92   - 'popularity': 'SELECT downloads * (1 + (rating_score/(rating_votes+0.01)/3)) FROM plugins_plugin AS pp WHERE pp.id = plugins_plugin.id'
  103 + 'popularity': 'plugins_plugin.downloads * (1 + (rating_score/(rating_votes+0.01)/3))'
93 104 }
94 105 ).order_by('-popularity').distinct()
95 106
96 107
97   -class TaggablePlugins (TaggableManager):
  108 +class MostDownloadedPlugins(ApprovedPlugins):
  109 + """
  110 + Shows only approved plugins, sort by downloads
  111 + """
  112 + def get_query_set(self):
  113 + return super(MostDownloadedPlugins, self).get_query_set().filter(deprecated=False).order_by('-downloads').distinct()
  114 +
  115 +
  116 +class MostVotedPlugins(ApprovedPlugins):
  117 + """
  118 + Shows only approved plugins, sort by vote number
  119 + """
  120 + def get_query_set(self):
  121 + return super(MostVotedPlugins, self).get_query_set().filter(deprecated=False).order_by('-rating_votes').distinct()
  122 +
  123 +
  124 +class MostRatedPlugins(ApprovedPlugins):
  125 + """
  126 + Shows only approved plugins, sort by vote/number of votes number
  127 + """
  128 + def get_query_set(self):
  129 + return super(ApprovedPlugins, self).get_query_set().filter(deprecated=False).order_by('-average_vote').distinct()
  130 +
  131 +
  132 +class TaggablePlugins(TaggableManager):
98 133 """
99 134 Shows only public plugins: i.e. those with "approved" flag set
100 135 """
@@ -146,6 +181,9 @@ class Plugin (models.Model):
146 181 unapproved_objects = UnapprovedPlugins()
147 182 deprecated_objects = DeprecatedPlugins()
148 183 popular_objects = PopularPlugins()
  184 + most_downloaded_objects = MostDownloadedPlugins()
  185 + most_voted_objects = MostVotedPlugins()
  186 + most_rated_objects = MostRatedPlugins()
149 187
150 188 rating = AnonymousRatingField(range=5, use_cookies=True, can_change_vote=True, allow_delete=True)
151 189
3  qgis-app/plugins/templates/plugins/plugin_base.html
@@ -28,6 +28,9 @@
28 28 <li><a href="{% url stable_plugins %}">{% trans "Stable"%}</a></li>
29 29 <li><a href="{% url experimental_plugins %}">{% trans "Experimental"%}</a></li>
30 30 <li><a href="{% url popular_plugins %}">{% trans "Popular" %}</a></li>
  31 + <li><a href="{% url most_voted_plugins %}">{% trans "Most voted" %}</a></li>
  32 + <li><a href="{% url most_downloaded_plugins %}">{% trans "Top downloads" %}</a></li>
  33 + <li><a href="{% url most_rated_plugins %}">{% trans "Most rated" %}</a></li>
31 34 </ul>
32 35 </div>
33 36 <div class="module_menu">
8 qgis-app/plugins/templates/plugins/plugin_detail.html
@@ -10,6 +10,12 @@
10 10 // these HTTP methods do not require CSRF protection
11 11 return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
12 12 }
  13 +
  14 + jQuery(document).ajaxStart(function () {
  15 + jQuery('#loading').show();
  16 + }).ajaxStop(function () {
  17 + jQuery('#loading').hide();
  18 + });
13 19
14 20 // Rating
15 21 jQuery(function(){
@@ -44,7 +50,7 @@
44 50 <h2>{% trans "Plugin" %}: {{ object.name }}{% if object.icon %}<img class="plugin-icon" src="{{ object.icon.url }}" alt="{% trans "Plugin icon" %}" />{% endif %}</h2>
45 51 <div class="plugin-details">
46 52 {% if object.deprecated %}<p class="error"><strong>{% trans "This plugin is deprecated!" %}</strong></p>{% endif %}
47   - <div id="rating"> (<span id="votes">{% firstof votes '0' %}</span>) {% trans "votes" %}&nbsp;<span id="vote-message" style="display:none"></span></div>
  53 + <div id="rating"> (<span id="votes">{% firstof votes '0' %}</span>) {% trans "votes" %}&nbsp;<span id="loading" style="display:none">Loading...</span><span id="vote-message" style="display:none"></span></div>
48 54 <p class="plugin-details-description">{{ object.description }}</p>
49 55 {% if object.author %}
50 56 <p><strong>{% trans "Author"%}:</strong> <a title="{% trans "Plugins by"%} {{ object.author }}" href="{% url author_plugins object.author|urlencode %}">{{ object.author }}</a></p>
8 qgis-app/plugins/templates/plugins/plugin_list.html
... ... @@ -1,4 +1,4 @@
1   -{% extends 'plugins/plugin_base.html' %}{% load i18n sorting_tags pagination_tags humanize smart_paginate %}
  1 +{% extends 'plugins/plugin_base.html' %}{% load i18n sorting_tags pagination_tags humanize smart_paginate range_filter %}
2 2 {% block extrajs %}
3 3 <script type="text/javascript" src="/static/js/jquery-1.5.1.min.js"></script>
4 4 <script type="text/javascript" src="/static/js/jquery.cookie.js"></script>
@@ -60,7 +60,10 @@
60 60 <th>{% anchor featured %}</th>
61 61 <th>{% anchor downloads %}</th>
62 62 <th>{% anchor author "Author" %}</th>
  63 +<!--
63 64 <th>{% anchor modified_on "Last modified" %}</th>
  65 +-->
  66 + <th>{% anchor average_vote "Stars (votes)" %}</th>
64 67 <th>{% trans "Stable" %}</th>
65 68 <th>{% trans "Exp." %}</th>
66 69 {% if user.is_authenticated %}<th colspan="2">{% trans "Manage" %}</th>{% endif %}
@@ -77,7 +80,10 @@
77 80 <td>{% if object.featured%}<img src="/static/images/tick_16.png" />{% else %}&mdash;{% endif %}</td>
78 81 <td>{{ object.downloads }}</td>
79 82 <td><a title="{% trans "Plugins by"%} {{ object.author }}" href="{% url author_plugins object.author|urlencode %}">{{ object.author }}</a></td>
  83 +<!--
80 84 <td>{{ object.modified_on|naturalday }}</td>
  85 +-->
  86 + <td>{% for i in object.average_vote|add:"0"|get_range %}<span class="small-star"></span>{% endfor %} ({{ object.rating_votes }})</td>
81 87 <td>{% if object.stable %}<a href="{% url version_download object.package_name object.stable.version %}" title="{% trans "Download the stable version" %}" >{{ object.stable.version }}</a>{% else %}&mdash;{% endif %}</td>
82 88 <td>{% if object.experimental %}<a href="{% url version_download object.package_name object.experimental.version %}" title="{% trans "Download the experimental version" %}" >{{ object.experimental.version }}</a>{% else %}&mdash;{% endif %}</td>
83 89 {% if user.is_authenticated %}{% if user in object.editors or user.is_staff %}<td><a href="{% url plugin_update object.package_name %}">{% trans "Edit" %}</a></td>
24 qgis-app/plugins/templatetags/range_filter.py
... ... @@ -0,0 +1,24 @@
  1 +from django.template import Library
  2 +
  3 +register = Library()
  4 +
  5 +@register.filter
  6 +def get_range( value ):
  7 + """
  8 + Filter - returns a list containing range made from given value
  9 + Usage (in template):
  10 +
  11 + <ul>{% for i in 3|get_range %}
  12 + <li>{{ i }}. Do something</li>
  13 + {% endfor %}</ul>
  14 +
  15 + Results with the HTML:
  16 + <ul>
  17 + <li>0. Do something</li>
  18 + <li>1. Do something</li>
  19 + <li>2. Do something</li>
  20 + </ul>
  21 +
  22 + Instead of 3 one may use the variable set in the views
  23 + """
  24 + return range( value )
4 qgis-app/plugins/urls.py
@@ -31,6 +31,10 @@
31 31 url(r'^stable/$', 'plugins_list', {'queryset' : Plugin.stable_objects.all(), 'extra_context' : {'title' : _('Stable plugins')}}, name='stable_plugins'),
32 32 url(r'^experimental/$', 'plugins_list', {'queryset' : Plugin.experimental_objects.all(), 'extra_context' : {'title' : _('Experimental plugins')}}, name='experimental_plugins'),
33 33 url(r'^popular/$', 'plugins_list', {'queryset' : Plugin.popular_objects.all(), 'extra_context' : {'title' : _('Popular plugins')}}, name='popular_plugins'),
  34 + url(r'^most_voted/$', 'plugins_list', {'queryset' : Plugin.most_voted_objects.all(), 'extra_context' : {'title' : _('Most voted plugins')}}, name='most_voted_plugins'),
  35 + url(r'^most_downloaded/$', 'plugins_list', {'queryset' : Plugin.most_downloaded_objects.all(), 'extra_context' : {'title' : _('Most downloaded plugins')}}, name='most_downloaded_plugins'),
  36 + url(r'^most_voted/$', 'plugins_list', {'queryset' : Plugin.most_voted_objects.all(), 'extra_context' : {'title' : _('Most voted plugins')}}, name='most_voted_plugins'),
  37 + url(r'^most_rated/$', 'plugins_list', {'queryset' : Plugin.most_rated_objects.all(), 'extra_context' : {'title' : _('Most rated plugins')}}, name='most_rated_plugins'),
34 38
35 39 url(r'^author/(?P<author>[^/]+)/$', 'author_plugins', {}, name='author_plugins'),
36 40
5 qgis-app/plugins/views.py
@@ -14,7 +14,7 @@
14 14 from django.conf import settings
15 15 from django.contrib.auth.models import User, Permission
16 16 from django.contrib.contenttypes.models import ContentType
17   -
  17 +from django.utils.encoding import DjangoUnicodeDecodeError
18 18 from plugins.models import Plugin, PluginVersion
19 19 from plugins.forms import *
20 20
@@ -238,6 +238,7 @@ def plugin_upload(request):
238 238 elif not plugin.repository:
239 239 warnings.append(_('<strong>repository</strong> field is empty, this field is not required but is recommended, please consider adding it to metadata.'))
240 240
  241 +
241 242 plugin.save()
242 243
243 244 if is_new:
@@ -274,7 +275,7 @@ def plugin_upload(request):
274 275 messages.warning(request, _('<p><strong>Warnings:</strong></p>') + '\n'.join(["<p>%s</p>" % unicode(w) for w in warnings]), fail_silently=True)
275 276
276 277
277   - except (IntegrityError, ValidationError), e:
  278 + except (IntegrityError, ValidationError, DjangoUnicodeDecodeError), e:
278 279 connection.close()
279 280 messages.error(request, e, fail_silently=True)
280 281 if not plugin.pk:
BIN  qgis-app/static/images/loading.gif
13 qgis-app/static/style/style.css
@@ -114,6 +114,7 @@ pre, .wp-caption-text {
114 114 width: 100%;
115 115 }
116 116
  117 +/* plugins */
117 118
118 119 div.plugin-details {
119 120 clear: both;
@@ -136,3 +137,15 @@ div.plugin-details .plugin-details-description{
136 137 -moz-border-radius: 10px;
137 138 border-radius: 10px;
138 139 }
  140 +
  141 +#loading {
  142 + background: url(../images/loading.gif) top left no-repeat;
  143 + padding-left: 20px;
  144 +}
  145 +
  146 +span.small-star {
  147 + background: url(../images/star_16.png) center bottom no-repeat;
  148 + width: 17px;
  149 + height: 17px;
  150 + display: inline-block;
  151 +}

0 comments on commit 2419a02

Please sign in to comment.
Something went wrong with that request. Please try again.