[extensions-web] Add and from now on populate 'popularity': (enables - disables)
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [extensions-web] Add and from now on populate 'popularity': (enables - disables)
- Date: Sun, 18 Dec 2011 00:50:49 +0000 (UTC)
commit 447fd5f6971db7256a1a8c9e359457752807214b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Dec 16 02:58:45 2011 -0500
Add and from now on populate 'popularity': (enables - disables)
An extension's popularity is the number of enables minus the number of
disables. Because Django's ORM isn't quite up to the task of doing this
math in the sorting of the query quite yet, we track this as three
separate fields in the database: enables, disables and popularity.
From now on, the JavaScript associated with enabling/disabling an
extension will also ping back to the server to keep track of this
anonymous data, used entirely for statistics.
...enables__add_field_extension_disables__add_f.py | 106 ++++++++++++++++++++
sweettooth/extensions/models.py | 4 +
sweettooth/extensions/urls.py | 1 +
sweettooth/extensions/views.py | 22 ++++-
sweettooth/static/js/extensions.js | 11 ++-
5 files changed, 142 insertions(+), 2 deletions(-)
---
diff --git a/sweettooth/extensions/migrations/0011_auto__add_field_extension_enables__add_field_extension_disables__add_f.py b/sweettooth/extensions/migrations/0011_auto__add_field_extension_enables__add_field_extension_disables__add_f.py
new file mode 100644
index 0000000..486d0fb
--- /dev/null
+++ b/sweettooth/extensions/migrations/0011_auto__add_field_extension_enables__add_field_extension_disables__add_f.py
@@ -0,0 +1,106 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding field 'Extension.enables'
+ db.add_column('extensions_extension', 'enables', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+
+ # Adding field 'Extension.disables'
+ db.add_column('extensions_extension', 'disables', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+
+ # Adding field 'Extension.popularity'
+ db.add_column('extensions_extension', 'popularity', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'Extension.enables'
+ db.delete_column('extensions_extension', 'enables')
+
+ # Deleting field 'Extension.disables'
+ db.delete_column('extensions_extension', 'disables')
+
+ # Deleting field 'Extension.popularity'
+ db.delete_column('extensions_extension', 'popularity')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'extensions.extension': {
+ 'Meta': {'object_name': 'Extension'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'disables': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'downloads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'enables': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'icon': ('django.db.models.fields.files.ImageField', [], {'default': "'/static/images/plugin.png'", 'max_length': '100', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ 'popularity': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'screenshot': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100', 'blank': 'True'}),
+ 'slug': ('autoslug.fields.AutoSlugField', [], {'unique_with': '()', 'max_length': '50', 'populate_from': 'None', 'db_index': 'True'}),
+ 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200', 'db_index': 'True'})
+ },
+ 'extensions.extensionversion': {
+ 'Meta': {'unique_together': "(('extension', 'version'),)", 'object_name': 'ExtensionVersion'},
+ 'extension': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'versions'", 'to': "orm['extensions.Extension']"}),
+ 'extra_json_fields': ('django.db.models.fields.TextField', [], {}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'shell_versions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['extensions.ShellVersion']", 'symmetrical': 'False'}),
+ 'source': ('django.db.models.fields.files.FileField', [], {'max_length': '223'}),
+ 'status': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'version': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+ },
+ 'extensions.shellversion': {
+ 'Meta': {'object_name': 'ShellVersion'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'major': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'minor': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'point': ('django.db.models.fields.IntegerField', [], {})
+ }
+ }
+
+ complete_apps = ['extensions']
diff --git a/sweettooth/extensions/models.py b/sweettooth/extensions/models.py
index 6931fc8..f7d807a 100644
--- a/sweettooth/extensions/models.py
+++ b/sweettooth/extensions/models.py
@@ -73,6 +73,10 @@ class Extension(models.Model):
created = models.DateTimeField(auto_now_add=True)
downloads = models.PositiveIntegerField(default=0)
+ enables = models.IntegerField(default=0)
+ disables = models.IntegerField(default=0)
+ popularity = models.IntegerField(default=0)
+
class Meta:
permissions = (
("can-modify-data", "Can modify extension data"),
diff --git a/sweettooth/extensions/urls.py b/sweettooth/extensions/urls.py
index bc9a154..6dc7214 100644
--- a/sweettooth/extensions/urls.py
+++ b/sweettooth/extensions/urls.py
@@ -21,6 +21,7 @@ ajax_patterns = patterns('',
url(r'^set-status/inactive/', views.ajax_set_status_view,
dict(newstatus=models.STATUS_INACTIVE), name='extensions-ajax-set-status-inactive'),
url(r'^extensions-list/', views.ajax_extensions_list),
+ url(r'^adjust-popularity/', views.ajax_adjust_popularity_view),
)
shell_patterns = patterns('',
diff --git a/sweettooth/extensions/views.py b/sweettooth/extensions/views.py
index 7dee4ef..935fe5a 100644
--- a/sweettooth/extensions/views.py
+++ b/sweettooth/extensions/views.py
@@ -4,7 +4,7 @@ from django.core.paginator import Paginator, InvalidPage
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.contrib import messages
-from django.http import HttpResponseForbidden, Http404
+from django.http import HttpResponseForbidden, HttpResponseServerError, Http404
from django.shortcuts import get_object_or_404, redirect
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
@@ -60,6 +60,8 @@ def ajax_query_params_query(request):
queryset = queryset.order_by('-pk')
elif sort == 'downloads':
queryset = queryset.order_by('-downloads')
+ elif sort == 'popularity':
+ queryset = queryset.order_by('-popularity')
else:
queryset = queryset.order_by('name')
@@ -212,6 +214,24 @@ def extension_version_view(request, obj, **kwargs):
return render(request, template_name, context)
@ajax_view
+def ajax_adjust_popularity_view(request):
+ uuid = request.GET['uuid']
+ action = request.GET['action']
+
+ extension = models.Extension.objects.get(uuid=uuid)
+
+ if action == 'enable':
+ extension.enables += 1
+ extension.popularity += 1
+ elif action == 'disable':
+ extension.disables += 1
+ extension.popularity -= 1
+ else:
+ return HttpResponseServerError()
+
+ extension.save()
+
+ ajax_view
@require_POST
@model_view(models.ExtensionVersion)
def ajax_submit_and_lock_view(request, obj):
diff --git a/sweettooth/static/js/extensions.js b/sweettooth/static/js/extensions.js
index 9e475f9..a23a692 100644
--- a/sweettooth/static/js/extensions.js
+++ b/sweettooth/static/js/extensions.js
@@ -100,6 +100,12 @@ function($, messages, dbusProxy, extensionUtils) {
if ($switch.hasClass('insensitive'))
return;
+ function sendPopularity(action) {
+ $.ajax({ url: '/ajax/adjust-popularity/',
+ data: { uuid: uuid,
+ action: action } });
+ }
+
$switch.bind('changed', function(e, newValue) {
var oldState = $elem.data('state');
if (newValue) {
@@ -110,10 +116,13 @@ function($, messages, dbusProxy, extensionUtils) {
} else if (oldState == ExtensionState.DISABLED ||
oldState == ExtensionState.INITIALIZED) {
dbusProxy.EnableExtension(uuid);
+ sendPopularity('enable');
}
} else {
- if (oldState == ExtensionState.ENABLED)
+ if (oldState == ExtensionState.ENABLED) {
dbusProxy.DisableExtension(uuid);
+ sendPopularity('disable');
+ }
}
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]