euscanwww: Watch/unwatch packages, categories, maintainers, overlays

Added a button for watch/unwatch and a dashboard with user selected
stuff only

Signed-off-by: volpino <fox91@anche.no>
This commit is contained in:
volpino 2012-07-10 16:15:06 +02:00
parent 02be58024a
commit fab19a6bfc
17 changed files with 507 additions and 59 deletions

View File

@ -52,13 +52,16 @@ class PackageMixin(object):
"""
return self.values('category').annotate(**ANNOTATE_DICT)
def herds(self, rename=False):
def herds(self, ids=None, rename=False):
"""
Returns all the available herds
"""
# FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of
# 'INNER JOIN'
res = self.filter(herds__isnull=False)
if ids is not None:
res = self.filter(herds__id__in=ids)
else:
res = self.filter(herds__isnull=False)
res = res.values('herds__herd').annotate(**ANNOTATE_DICT)
if rename:
@ -66,11 +69,16 @@ class PackageMixin(object):
return res
def maintainers(self, rename=False):
def maintainers(self, ids=None, rename=False):
"""
Returns all the available maintainers
"""
res = self.filter(maintainers__isnull=False).values(
if ids is not None:
res = self.filter(maintainers__id__in=ids)
else:
res = self.filter(maintainers__isnull=False)
res = res.values(
'maintainers__id', 'maintainers__name', 'maintainers__email'
)
res = res.annotate(**ANNOTATE_DICT)
@ -90,7 +98,7 @@ class PackageMixin(object):
Returns the all available overlays
"""
res = self.values('version__overlay').exclude(version__overlay='')
return res.distinct()
return [o["version__overlay"] for o in res.distinct()]
def for_overlay(self, overlay):
"""

View File

@ -0,0 +1,207 @@
# -*- coding: 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 model 'OverlayAssociation'
db.create_table('djeuscan_overlayassociation', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
('overlay', self.gf('django.db.models.fields.CharField')(max_length=128)),
))
db.send_create_signal('djeuscan', ['OverlayAssociation'])
# Adding unique constraint on 'OverlayAssociation', fields ['user', 'overlay']
db.create_unique('djeuscan_overlayassociation', ['user_id', 'overlay'])
def backwards(self, orm):
# Removing unique constraint on 'OverlayAssociation', fields ['user', 'overlay']
db.delete_unique('djeuscan_overlayassociation', ['user_id', 'overlay'])
# Deleting model 'OverlayAssociation'
db.delete_table('djeuscan_overlayassociation')
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'})
},
'djeuscan.categoryassociation': {
'Meta': {'unique_together': "(['user', 'category'],)", 'object_name': 'CategoryAssociation'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'djeuscan.categorylog': {
'Meta': {'object_name': 'CategoryLog', '_ormbases': ['djeuscan.Log']},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['djeuscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'djeuscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'ebuild': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'scan_time': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'})
},
'djeuscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'djeuscan.herdassociation': {
'Meta': {'unique_together': "(['user', 'herd'],)", 'object_name': 'HerdAssociation'},
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Herd']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'djeuscan.herdlog': {
'Meta': {'object_name': 'HerdLog', '_ormbases': ['djeuscan.Log']},
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Herd']"}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['djeuscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'djeuscan.log': {
'Meta': {'object_name': 'Log'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'djeuscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'djeuscan.maintainerassociation': {
'Meta': {'unique_together': "(['user', 'maintainer'],)", 'object_name': 'MaintainerAssociation'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Maintainer']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'djeuscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog', '_ormbases': ['djeuscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['djeuscan.Log']", 'unique': 'True', 'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Maintainer']"})
},
'djeuscan.overlayassociation': {
'Meta': {'unique_together': "(['user', 'overlay'],)", 'object_name': 'OverlayAssociation'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'djeuscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_version_gentoo': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_version_gentoo'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['djeuscan.Version']"}),
'last_version_overlay': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_version_overlay'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['djeuscan.Version']"}),
'last_version_upstream': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_version_upstream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['djeuscan.Version']"}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'djeuscan.packageassociation': {
'Meta': {'unique_together': "(['user', 'package'],)", 'object_name': 'PackageAssociation'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'djeuscan.problemreport': {
'Meta': {'object_name': 'ProblemReport'},
'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.TextField', [], {}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}),
'subject': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Version']", 'null': 'True', 'blank': 'True'})
},
'djeuscan.refreshpackagequery': {
'Meta': {'object_name': 'RefreshPackageQuery'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}),
'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'djeuscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'alive': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
'confidence': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'handler': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128', 'db_index': 'True', 'blank': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'version_type': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'})
},
'djeuscan.versionlog': {
'Meta': {'object_name': 'VersionLog'},
'action': ('django.db.models.fields.IntegerField', [], {}),
'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128', 'blank': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['djeuscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'djeuscan.worldlog': {
'Meta': {'object_name': 'WorldLog', '_ormbases': ['djeuscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['djeuscan.Log']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['djeuscan']

View File

@ -130,6 +130,9 @@ class Version(models.Model):
handler = models.CharField(max_length=128, blank=True)
confidence = models.IntegerField(default=0)
ebuild_path = models.CharField(blank=True, max_length=256)
metadata_path = models.CharField(blank=True, max_length=256)
class Meta:
unique_together = ['package', 'slot', 'revision', 'version', 'overlay']
@ -320,6 +323,17 @@ class CategoryAssociation(models.Model):
return u'[%s] %s' % (self.user, self.category)
class OverlayAssociation(models.Model):
user = models.ForeignKey(User)
overlay = models.CharField(max_length=128, validators=[validate_name])
class Meta:
unique_together = ['user', 'overlay']
def __unicode__(self):
return u'[%s] %s' % (self.user, self.category)
class ProblemReport(models.Model):
package = models.ForeignKey(Package)
version = models.ForeignKey(Version, null=True, blank=True)

View File

@ -56,6 +56,7 @@
<li><a href="{% url "accounts_herds" %}">Herds</a></li>
<li><a href="{% url "accounts_maintainers" %}">Maintainers</a></li>
<li><a href="{% url "accounts_packages" %}">Packages</a></li>
<li><a href="{% url "accounts_overlays" %}">Overlays</a></li>
</ul>
<li><a href="{% url "django.contrib.auth.views.logout" %}">Logout</a></li>
{% else %}

View File

@ -0,0 +1,18 @@
{% load url from future %}
<table id="table" class="display">
<thead>
<th>Overlay</th>
</thead>
<tbody>
{% for overlay in overlays %}
<tr>
<td>
<a href="{% url "overlay" overlay %}">
{{ overlay }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,15 @@
{% extends "euscan/_datatable.html" %}
{% load euscan %}
{% load url from future %}
{% block title %}
{{ block.super }} - Watched overlays
{% endblock %}
{% block content %}
<h2>Watched overlays</h2>
{% overlays_table overlays %}
{% endblock %}

View File

@ -16,7 +16,18 @@
{% endblock %}
{% block content %}
<h2>Category: {{ category }}</h2>
<h2>
Category: {{ category }}
{% if user.is_authenticated %}
<button class="btn favourite-button {% if favourited %}hide{% endif %}" data-url="{% url "favourite_category" category %}">
Watch
</button>
<button class="btn unfavourite-button {% if not favourited %}hide{% endif %}" data-url="{% url "unfavourite_category" category %}">
Unwatch
</button>
{% endif %}
</h2>
{% packages packages %}
@ -38,11 +49,27 @@
<img src="{% url "chart_category" category 'packages-monthly' %}" />
</p>
<script type="text/javascript">
$(".favourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".unfavourite-button").removeClass("hide");
$(".favourite-button").addClass("hide");
});
});
$(".unfavourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".favourite-button").removeClass("hide");
$(".unfavourite-button").addClass("hide");
});
});
</script>
{% endblock %}
{% block menus %}
{{ block.super }}
<div class="menu">
<div class="menu rounded notfirst-menu">
<dl>
<dt>Versions</dt>
<dd><img src="{% url "chart_category" category 'versions-monthly-small' %}" /></dd>
@ -50,5 +77,4 @@
<dd><img src="{% url "chart_category" category 'packages-monthly-small' %}" /></dd>
</dl>
</div>
{% endblock %}

View File

@ -16,7 +16,18 @@
{% endblock %}
{% block content %}
<h2>Herd: {{ herd.herd }}</h2>
<h2>
Herd: {{ herd.herd }}
{% if user.is_authenticated %}
<button class="btn favourite-button {% if favourited %}hide{% endif %}" data-url="{% url "favourite_herd" herd.herd %}">
Watch
</button>
<button class="btn unfavourite-button {% if not favourited %}hide{% endif %}" data-url="{% url "unfavourite_herd" herd.herd %}">
Unwatch
</button>
{% endif %}
</h2>
{% packages packages %}
<h3>Statistics</h2>
@ -36,11 +47,27 @@
<img src="{% url "chart_herd" herd.herd 'packages-monthly' %}" />
</p>
<script type="text/javascript">
$(".favourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".unfavourite-button").removeClass("hide");
$(".favourite-button").addClass("hide");
});
});
$(".unfavourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".favourite-button").removeClass("hide");
$(".unfavourite-button").addClass("hide");
});
});
</script>
{% endblock %}
{% block menus %}
{{ block.super }}
<div class="menu">
<div class="menu rounded notfirst-menu">
<dl>
<dt>Versions</dt>
<dd><img src="{% url "chart_herd" herd.herd 'versions-monthly-small' %}" /></dd>

View File

@ -18,7 +18,17 @@
{% endblock %}
{% block content %}
<h2>Maintainer: {{ maintainer.name }} &lt{{ maintainer.email }}&gt</h2>
<h2>
Maintainer: {{ maintainer.name }} &lt{{ maintainer.email }}&gt
{% if user.is_authenticated %}
<button class="btn favourite-button {% if favourited %}hide{% endif %}" data-url="{% url "favourite_maintainer" maintainer.id %}">
Watch
</button>
<button class="btn unfavourite-button {% if not favourited %}hide{% endif %}" data-url="{% url "unfavourite_maintainer" maintainer.id %}">
Unwatch
</button>
{% endif %}
</h2>
{% packages packages %}
<h3>Statistics</h2>
@ -38,11 +48,28 @@
<img src="{% url "chart_maintainer" maintainer.id 'packages-weekly' %}" />
<img src="{% url "chart_maintainer" maintainer.id 'packages-monthly' %}" />
</p>
<script type="text/javascript">
$(".favourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".unfavourite-button").removeClass("hide");
$(".favourite-button").addClass("hide");
});
});
$(".unfavourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".favourite-button").removeClass("hide");
$(".unfavourite-button").addClass("hide");
});
});
</script>
{% endblock %}
{% block menus %}
{{ block.super }}
<div class="menu">
<div class="menu rounded notfirst-menu">
<dl>
<dt>Versions</dt>
<dd><img src="{% url "chart_maintainer" maintainer.id 'versions-monthly-small' %}" /></dd>
@ -52,4 +79,3 @@
</div>
{% endblock %}
5A

View File

@ -1,5 +1,6 @@
{% extends "euscan/_datatable.html" %}
{% load url from future %}
{% load euscan %}
{% block title %}
@ -7,6 +8,35 @@
{% endblock %}
{% block content %}
<h2>Overlay: {{ overlay }}</h2>
<h2>
Overlay: {{ overlay }}
{% if user.is_authenticated %}
<button class="btn favourite-button {% if favourited %}hide{% endif %}" data-url="{% url "favourite_overlay" overlay %}">
Watch
</button>
<button class="btn unfavourite-button {% if not favourited %}hide{% endif %}" data-url="{% url "unfavourite_overlay" overlay %}">
Unwatch
</button>
{% endif %}
</h2>
{% packages packages %}
<script type="text/javascript">
$(".favourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".unfavourite-button").removeClass("hide");
$(".favourite-button").addClass("hide");
});
});
$(".unfavourite-button").click(function() {
$.post($(this).data("url"), function() {
$(".favourite-button").removeClass("hide");
$(".unfavourite-button").addClass("hide");
});
});
</script>
{% endblock %}

View File

@ -10,20 +10,6 @@
{% block content %}
<h2>Overlays</h2>
<table id="table" class="display">
<thead>
<th>Overlay</th>
</thead>
<tbody>
{% for overlay in overlays %}
<tr>
<td>
<a href="{% url "overlay" overlay.version__overlay %}">
{{ overlay.version__overlay }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% overlays_table overlays %}
{% endblock %}

View File

@ -39,10 +39,10 @@
Refresh
</button>
<button class="btn favourite-button {% if favourited %}hide{% endif %}" data-url="{% url "favourite_package" package.category package.name %}">
Add to favourites
Watch
</button>
<button class="btn unfavourite-button {% if not favourited %}hide{% endif %}" data-url="{% url "unfavourite_package" package.category package.name %}">
Remove from favourites
Unwatch
</button>
{% endif %}
</h2>

View File

@ -47,3 +47,11 @@ def maintainers_table(maintainers, extras=False):
"extras": extras,
"STATIC_URL": settings.STATIC_URL,
}
@register.inclusion_tag('euscan/_overlays_table.html')
def overlays_table(overlays):
return {
"overlays": overlays,
"STATIC_URL": settings.STATIC_URL,
}

View File

@ -88,8 +88,7 @@ class PackageModelTests(TestCase):
def test_overlays(self):
overlays, packages = setup_overlays()
overlay_names = [o["version__overlay"]
for o in Package.objects.overlays()]
overlay_names = Package.objects.overlays()
for overlay in overlays:
self.assertTrue(overlay in overlay_names)

View File

@ -16,10 +16,10 @@ package_patterns = patterns('djeuscan.views',
PackageFeed(), name='package_feed'),
url(r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/$',
'package', name="package"),
url(r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/favourite$',
url(r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/favourite/$',
'favourite_package', name="favourite_package"),
url((r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/'
'unfavourite$'), 'unfavourite_package', name="unfavourite_package"),
'unfavourite/$'), 'unfavourite_package', name="unfavourite_package"),
url((r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/'
'refresh$'), "refresh_package", name="refresh_package"),
)
@ -31,9 +31,9 @@ categories_patterns = patterns('djeuscan.views',
name='category_feed'),
url(r'^(?P<category>[\w+][\w+.-]*)/charts/(?P<chart>[\w\-]+).png$',
'chart_category', name="chart_category"),
url(r'^(?P<category>[\w+][\w+.-]*)/favourite$',
url(r'^(?P<category>[\w+][\w+.-]*)/favourite/$',
'favourite_category', name="favourite_category"),
url(r'^(?P<category>[\w+][\w+.-]*)/unfavourite$',
url(r'^(?P<category>[\w+][\w+.-]*)/unfavourite/$',
'unfavourite_category', name="unfavourite_category"),
url(r'^$', 'categories', name="categories"),
)
@ -43,9 +43,9 @@ herds_patterns = patterns('djeuscan.views',
url(r'^(?P<herd>[\@\{\}\w+.-]*)/feed/$', HerdFeed(), name='herd_feed'),
url(r'^(?P<herd>[\@\{\}\w+.-]*)/charts/(?P<chart>[\w\-]+).png$',
'chart_herd', name="chart_herd"),
url(r'^(?P<herd>[\@\{\}\w+.-]*)/favourite$', 'favourite_herd',
url(r'^(?P<herd>[\@\{\}\w+.-]*)/favourite/$', 'favourite_herd',
name="favourite_herd"),
url(r'^(?P<herd>[\@\{\}\w+.-]*)/unfavourite$', 'unfavourite_herd',
url(r'^(?P<herd>[\@\{\}\w+.-]*)/unfavourite/$', 'unfavourite_herd',
name="unfavourite_herd"),
url(r'^$', 'herds', name="herds"),
)
@ -56,15 +56,19 @@ maintainers_patterns = patterns('djeuscan.views',
name='maintainer_feed'),
url(r'^(?P<maintainer_id>\d+)/charts/(?P<chart>[\w\-]+).png$',
'chart_maintainer', name="chart_maintainer"),
url(r'^(?P<maintainer_id>\d+)/favourite$',
url(r'^(?P<maintainer_id>\d+)/favourite/$',
'favourite_maintainer', name="favourite_maintainer"),
url(r'^(?P<maintainer_id>\d+)/unfavourite$',
url(r'^(?P<maintainer_id>\d+)/unfavourite/$',
'unfavourite_maintainer', name="unfavourite_maintainer"),
url(r'^$', 'maintainers', name="maintainers"),
)
overlays_patterns = patterns('djeuscan.views',
url(r'^(?P<overlay>[\w+][\w+.-]*)/(view/)?$', 'overlay', name="overlay"),
url(r'^(?P<overlay>[\w+][\w+.-]*)/favourite/$', 'favourite_overlay',
name="favourite_overlay"),
url(r'^(?P<overlay>[\w+][\w+.-]*)/unfavourite/$', 'unfavourite_overlay',
name="unfavourite_overlay"),
url(r'^$', 'overlays', name="overlays"),
)
@ -82,6 +86,7 @@ accounts_patterns = patterns('djeuscan.views',
url(r'^maintainers/$', 'accounts_maintainers',
name="accounts_maintainers"),
url(r'^packages/$', 'accounts_packages', name="accounts_packages"),
url(r'^overlays/$', 'accounts_overlays', name="accounts_overlays"),
)

View File

@ -11,7 +11,7 @@ from django.views.decorators.http import require_POST
from djeuscan.helpers import version_key, packages_from_names
from djeuscan.models import Version, Package, Herd, Maintainer, EuscanResult, \
VersionLog, RefreshPackageQuery, HerdAssociation, MaintainerAssociation, \
CategoryAssociation, PackageAssociation, ProblemReport
CategoryAssociation, PackageAssociation, OverlayAssociation, ProblemReport
from djeuscan.forms import WorldForm, PackagesForm, ProblemReportForm
from djeuscan.tasks import admin_tasks
from djeuscan import charts
@ -64,7 +64,18 @@ def category(request, category):
except EuscanResult.DoesNotExist:
last_scan = None
return {'category': category, 'packages': packages, 'last_scan': last_scan}
favourited = False
if request.user.is_authenticated():
try:
CategoryAssociation.objects.get(user=request.user,
category=category)
except CategoryAssociation.DoesNotExist:
pass
else:
favourited = True
return {'category': category, 'packages': packages, 'last_scan': last_scan,
'favourited': favourited}
@render_to('euscan/herds.html')
@ -89,7 +100,17 @@ def herd(request, herd):
except EuscanResult.DoesNotExist:
last_scan = None
return {'herd': herd, 'packages': packages, "last_scan": last_scan}
favourited = False
if request.user.is_authenticated():
try:
HerdAssociation.objects.get(user=request.user, herd=herd)
except HerdAssociation.DoesNotExist:
pass
else:
favourited = True
return {'herd': herd, 'packages': packages, "last_scan": last_scan,
'favourited': favourited}
@render_to('euscan/maintainers.html')
@ -115,11 +136,18 @@ def maintainer(request, maintainer_id):
except EuscanResult.DoesNotExist:
last_scan = None
return {
'maintainer': maintainer,
'packages': packages,
'last_scan': last_scan
}
favourited = False
if request.user.is_authenticated():
try:
MaintainerAssociation.objects.get(user=request.user,
maintainer=maintainer)
except MaintainerAssociation.DoesNotExist:
pass
else:
favourited = True
return {'maintainer': maintainer, 'packages': packages,
'last_scan': last_scan, 'favourited': favourited}
@render_to('euscan/overlays.html')
@ -145,7 +173,17 @@ def overlay(request, overlay):
except EuscanResult.DoesNotExist:
last_scan = None
return {'overlay': overlay, 'packages': packages, 'last_scan': last_scan}
favourited = False
if request.user.is_authenticated():
try:
OverlayAssociation.objects.get(user=request.user, overlay=overlay)
except OverlayAssociation.DoesNotExist:
pass
else:
favourited = True
return {'overlay': overlay, 'packages': packages, 'last_scan': last_scan,
'favourited': favourited}
@render_to('euscan/package.html')
@ -327,24 +365,28 @@ def accounts_index(request):
@login_required
@render_to('euscan/accounts/categories.html')
def accounts_categories(request):
categories = [obj.category for obj in
CategoryAssociation.objects.filter(user=request.user)]
category_names = [obj.category for obj in
CategoryAssociation.objects.filter(user=request.user)]
categories = [c for c in Package.objects.categories()
if c["category"] in category_names]
return {"categories": categories}
@login_required
@render_to('euscan/accounts/herds.html')
def accounts_herds(request):
herds = [obj.herd for obj in
HerdAssociation.objects.filter(user=request.user)]
ids = [obj.herd.pk for obj in
HerdAssociation.objects.filter(user=request.user)]
herds = Package.objects.herds(ids=ids)
return {"herds": herds}
@login_required
@render_to('euscan/accounts/maintainers.html')
def accounts_maintainers(request):
maintainers = [obj.maintainer for obj in
MaintainerAssociation.objects.filter(user=request.user)]
ids = [obj.maintainer.pk for obj in
MaintainerAssociation.objects.filter(user=request.user)]
maintainers = Package.objects.maintainers(ids=ids)
return {"maintainers": maintainers}
@ -356,6 +398,14 @@ def accounts_packages(request):
return {"packages": packages}
@login_required
@render_to('euscan/accounts/overlays.html')
def accounts_overlays(request):
overlays = [obj.overlay for obj in
OverlayAssociation.objects.filter(user=request.user)]
return {"overlays": overlays}
@login_required
@require_POST
@ajax_request
@ -449,3 +499,28 @@ def unfavourite_category(request, category):
)
obj.delete()
return {"success": True}
@login_required
@require_POST
@ajax_request
def favourite_overlay(request, overlay):
packages = Package.objects.for_overlay(overlay)
if not packages:
raise Http404
_, created = OverlayAssociation.objects.get_or_create(
user=request.user, overlay=overlay
)
return {"success": created}
@login_required
@require_POST
@ajax_request
def unfavourite_overlay(request, overlay):
obj = get_object_or_404(
OverlayAssociation, user=request.user, overlay=overlay
)
obj.delete()
return {"success": True}

View File

@ -13,11 +13,14 @@ settings.configure(
DATABASES={
'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}
},
INSTALLED_APPS=['euscanwww.euscanwww', 'djeuscan'],
INSTALLED_APPS=['euscanwww.euscanwww', 'djeuscan', 'django.contrib.auth',
'django.contrib.contenttypes'],
ROOT_URLCONF='euscanwww.euscanwww.urls',
EUSCAN_ROOT=EUSCAN_ROOT,
RRD_ROOT=os.path.join(EUSCAN_ROOT, 'var', 'rrd'),
USE_TZ=True
USE_TZ=True,
TASKS_CONCURRENTLY=8,
TASKS_SUBTASK_PACKAGES=32,
)