euscanwww: Moving all account related stuff to a separate app

Note: This commit could break things, the userprofile model has been
moved so the db layout must change (some alter table commands are
needed to don't lose data)

Signed-off-by: volpino <fox91@anche.no>
This commit is contained in:
volpino
2012-11-02 17:33:00 +01:00
parent 2bf0061979
commit c31076ddb4
31 changed files with 696 additions and 439 deletions

View File

View File

@ -0,0 +1,4 @@
from django.contrib import admin
from euscan_accounts.models import UserProfile
admin.site.register(UserProfile)

View File

@ -0,0 +1,26 @@
from djeuscan.feeds import BaseFeed
from euscan_accounts.helpers import get_profile, get_account_versionlogs
class UserFeed(BaseFeed):
link = "/"
def description(self, data):
return "%s - last euscan changes" % data["user"]
def title(self, data):
return "%s - watched packages" % data["user"]
def get_object(self, request):
return {
"user": request.user,
"options": request.GET,
}
def _items(self, data):
user = data["user"]
profile = get_profile(user)
vlogs = get_account_versionlogs(profile)
return vlogs, 100

View File

@ -0,0 +1,38 @@
from django import forms
from euscan_accounts.models import UserProfile
class PreferencesForm(forms.Form):
first_name = forms.CharField(max_length=30, required=False)
last_name = forms.CharField(max_length=30, required=False)
email = forms.EmailField()
feed_upstream_info = forms.BooleanField(required=False,
label="Upstream info")
feed_portage_info = forms.BooleanField(required=False,
label="Portage info")
feed_show_adds = forms.BooleanField(required=False,
label="Show version bumps")
feed_show_removals = forms.BooleanField(required=False,
label="Show version removals")
feed_ignore_pre = forms.BooleanField(required=False,
label="Ignore unstable releases")
feed_ignore_pre_if_stable = forms.BooleanField(
required=False,
label="Ignore unstable releases if current version is stable"
)
email_activated = forms.BooleanField(
required=False, label="Receive euscan emails"
)
email_every = forms.ChoiceField(
choices=UserProfile.EMAIL_OPTS,
label="Send email",
)
email_ignore_pre = forms.BooleanField(
required=False, label="Ignore unstable releases"
)
email_ignore_pre_if_stable = forms.BooleanField(
required=False,
label="Ignore unstable releases if current version is stable"
)

View File

@ -0,0 +1,81 @@
from django.db.models import Q
def get_profile(user):
from euscan_accounts.models import UserProfile
try:
return user.get_profile()
except UserProfile.DoesNotExist:
UserProfile.objects.create(user=user)
return user.get_profile()
def get_account_categories(user):
from djeuscan.models import Package
# TODO: This is quite ugly
category_names = [obj.name for obj in get_profile(user).categories.all()]
return [c for c in Package.objects.categories()
if c["category"] in category_names]
def get_account_herds(user):
from djeuscan.models import Package
ids = [herd.pk for herd in get_profile(user).herds.all()]
return Package.objects.herds(ids=ids)
def get_account_maintainers(user):
from djeuscan.models import Package
ids = [obj.pk for obj in get_profile(user).maintainers.all()]
return Package.objects.maintainers(ids=ids)
def get_account_versionlogs(profile):
"""
Returns all watched packages
"""
from djeuscan.models import Package, VersionLog
q_categories = Q(category__in=[
category.name for category in profile.categories.all()])
q_herds = Q(herds__in=profile.herds.all())
q_maintainers = Q(maintainers__in=profile.maintainers.all())
packages = list(profile.packages.all()) + list(Package.objects.filter(
q_categories | q_herds | q_maintainers))
overlays = [o.name for o in profile.overlays.all()]
return VersionLog.objects.filter(
Q(package__in=packages) | Q(overlay__in=overlays)
)
def get_user_fav_infos(user):
upstream_k = lambda c: c["n_versions"] - c["n_packaged"] - c["n_overlay"]
categories = sorted(get_account_categories(user),
key=upstream_k, reverse=True)
c_upstream = sum([upstream_k(c) for c in categories])
herds = sorted(get_account_herds(user),
key=upstream_k, reverse=True)
h_upstream = sum([upstream_k(c) for c in herds])
maintainers = sorted(get_account_maintainers(user),
key=upstream_k, reverse=True)
m_upstream = sum([upstream_k(c) for c in maintainers])
packages = sorted(
get_profile(user).packages.all(),
key=lambda p: p.n_versions - p.n_packaged - p.n_overlay,
reverse=True
)
p_upstream = sum(
[c.n_versions - c.n_packaged - c.n_overlay for c in packages]
)
return {
"categories": categories, "categories_upstream": c_upstream,
"herds": herds, "herds_upstream": h_upstream,
"maintainers": maintainers, "maintainers_upstream": m_upstream,
"packages": packages, "packages_upstream": p_upstream,
}

View File

@ -0,0 +1,204 @@
# -*- 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 'UserProfile'
db.create_table('euscan_accounts_userprofile', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)),
('feed_upstream_info', self.gf('django.db.models.fields.BooleanField')(default=True)),
('feed_portage_info', self.gf('django.db.models.fields.BooleanField')(default=False)),
('feed_show_adds', self.gf('django.db.models.fields.BooleanField')(default=True)),
('feed_show_removals', self.gf('django.db.models.fields.BooleanField')(default=True)),
('feed_ignore_pre', self.gf('django.db.models.fields.BooleanField')(default=False)),
('feed_ignore_pre_if_stable', self.gf('django.db.models.fields.BooleanField')(default=False)),
('email_activated', self.gf('django.db.models.fields.BooleanField')(default=True)),
('email_every', self.gf('django.db.models.fields.IntegerField')(default=1)),
('email_ignore_pre', self.gf('django.db.models.fields.BooleanField')(default=False)),
('email_ignore_pre_if_stable', self.gf('django.db.models.fields.BooleanField')(default=False)),
('last_email', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
))
db.send_create_signal('euscan_accounts', ['UserProfile'])
# Adding M2M table for field herds on 'UserProfile'
db.create_table('euscan_accounts_userprofile_herds', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)),
('herd', models.ForeignKey(orm['djeuscan.herd'], null=False))
))
db.create_unique('euscan_accounts_userprofile_herds', ['userprofile_id', 'herd_id'])
# Adding M2M table for field maintainers on 'UserProfile'
db.create_table('euscan_accounts_userprofile_maintainers', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)),
('maintainer', models.ForeignKey(orm['djeuscan.maintainer'], null=False))
))
db.create_unique('euscan_accounts_userprofile_maintainers', ['userprofile_id', 'maintainer_id'])
# Adding M2M table for field packages on 'UserProfile'
db.create_table('euscan_accounts_userprofile_packages', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)),
('package', models.ForeignKey(orm['djeuscan.package'], null=False))
))
db.create_unique('euscan_accounts_userprofile_packages', ['userprofile_id', 'package_id'])
# Adding M2M table for field categories on 'UserProfile'
db.create_table('euscan_accounts_userprofile_categories', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)),
('category', models.ForeignKey(orm['djeuscan.category'], null=False))
))
db.create_unique('euscan_accounts_userprofile_categories', ['userprofile_id', 'category_id'])
# Adding M2M table for field overlays on 'UserProfile'
db.create_table('euscan_accounts_userprofile_overlays', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('userprofile', models.ForeignKey(orm['euscan_accounts.userprofile'], null=False)),
('overlay', models.ForeignKey(orm['djeuscan.overlay'], null=False))
))
db.create_unique('euscan_accounts_userprofile_overlays', ['userprofile_id', 'overlay_id'])
def backwards(self, orm):
# Deleting model 'UserProfile'
db.delete_table('euscan_accounts_userprofile')
# Removing M2M table for field herds on 'UserProfile'
db.delete_table('euscan_accounts_userprofile_herds')
# Removing M2M table for field maintainers on 'UserProfile'
db.delete_table('euscan_accounts_userprofile_maintainers')
# Removing M2M table for field packages on 'UserProfile'
db.delete_table('euscan_accounts_userprofile_packages')
# Removing M2M table for field categories on 'UserProfile'
db.delete_table('euscan_accounts_userprofile_categories')
# Removing M2M table for field overlays on 'UserProfile'
db.delete_table('euscan_accounts_userprofile_overlays')
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.category': {
'Meta': {'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
},
'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'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Maintainer']", 'symmetrical': 'False'})
},
'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.overlay': {
'Meta': {'object_name': 'Overlay'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
},
'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.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'}),
'ebuild_path': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'handler': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'metadata_path': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': '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'}),
'vtype': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'})
},
'euscan_accounts.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Category']", 'symmetrical': 'False'}),
'email_activated': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'email_every': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
'email_ignore_pre': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'email_ignore_pre_if_stable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'feed_ignore_pre': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'feed_ignore_pre_if_stable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'feed_portage_info': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'feed_show_adds': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'feed_show_removals': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'feed_upstream_info': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Herd']", 'symmetrical': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_email': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Maintainer']", 'symmetrical': 'False'}),
'overlays': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Overlay']", 'symmetrical': 'False'}),
'packages': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['djeuscan.Package']", 'symmetrical': 'False'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
}
}
complete_apps = ['euscan_accounts']

View File

@ -0,0 +1,35 @@
from django.db import models
from django.contrib.auth.models import User
from djeuscan.models import Herd, Maintainer, Package, Category, Overlay
class UserProfile(models.Model):
EMAIL_SCAN = 1
EMAIL_WEEKLY = 2
EMAIL_MONTHLY = 3
EMAIL_OPTS = (
(EMAIL_SCAN, 'On updates'),
(EMAIL_WEEKLY, 'Weekly'),
(EMAIL_MONTHLY, 'Monthly')
)
user = models.OneToOneField(User)
herds = models.ManyToManyField(Herd)
maintainers = models.ManyToManyField(Maintainer)
packages = models.ManyToManyField(Package)
categories = models.ManyToManyField(Category)
overlays = models.ManyToManyField(Overlay)
feed_upstream_info = models.BooleanField(default=True)
feed_portage_info = models.BooleanField(default=False)
feed_show_adds = models.BooleanField(default=True)
feed_show_removals = models.BooleanField(default=True)
feed_ignore_pre = models.BooleanField(default=False)
feed_ignore_pre_if_stable = models.BooleanField(default=False)
email_activated = models.BooleanField(default=True)
email_every = models.IntegerField(choices=EMAIL_OPTS, default=EMAIL_SCAN)
email_ignore_pre = models.BooleanField(default=False)
email_ignore_pre_if_stable = models.BooleanField(default=False)
last_email = models.DateTimeField(auto_now_add=True)

View File

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

View File

@ -0,0 +1,32 @@
{% load djeuscan_helpers %}{% load sub %}Hello {{ user }},
{% if vlogs %}euscan news:
{% for vlog in vlogs %} * {{ vlog.package|ljust:"35" }} {{ vlog.version }} {% if vlog.vtype and not vlog.vtype|is_stable %}({{ vlog.vtype }}){% endif %}
{% endfor %}
{% endif %}
Summary:
{% with categories|length as num_categories %}{% if num_categories %}
Watching {{ num_categories }} categor{{ num_categories|pluralize:"y,ies"}}: {{ categories_upstream }} upstream version{{ categories_upstream|pluralize:"s"}}
{% if categories_upstream %}Hot categories:
{% for c in categories|slice:":3" %} * {{ c.category }} ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})
{% endfor %}
{% endif %}{% endif %}{% endwith %}{% with herds|length as num_herds %}{% if num_herds %}
Watching {{ num_herds }} herd{{ num_herds|pluralize:"s"}}: {{ herds_upstream }} upstream version{{ herds_upstream|pluralize:"s"}}
{% if herds_upstream %}Hot herds:
{% for c in herds|slice:":3" %} * {{ c.herds__herd }} ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})
{% endfor %}
{% endif %}{% endif %}{% endwith %}{% with maintainers|length as num_maintainers %}{% if num_maintainers %}
Watching {{ num_maintainers }} maintainer{{ num_maintainers|pluralize:"s"}}: {{ maintainers_upstream }} upstream version{{ maintainers_upstream|pluralize:"s"}}
{% if maintainers_upstream %}Hot maintainers:
{% for c in maintainers|slice:":3" %} * {{ c.maintainers__name }} ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})
{% endfor %}
{% endif %}{% endif %}{% endwith %}{% with packages|length as num_packages %}{% if num_packages %}
Watching {{ num_packages }} package{{ num_packages|pluralize:"s"}}: {{ packages_upstream }} upstream version{{ packages_upstream|pluralize:"s"}}
{% if packages_upstream %}Hot packages:
{% for c in packages|slice:":3" %} * {{ c }} ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})
{% endfor %}
{% endif %}{% endif %}{% endwith %}
--
This email was sent by euscan, please do not reply.
Go to your euscan account to change email notification settings.

View File

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

View File

@ -0,0 +1,110 @@
{% extends "_base.html" %}
{% load url from future %}
{% load sub %}
{% block title %}
{{ block.super }} - Welcome {{ user }}
{% endblock %}
{% block content %}
<h2>
Welcome {{ user }}
<span class="pull-right">
<a href="{% url "auth_password_change" %}" class="btn">
Change password
</a>
<a href="{% url "accounts_preferences" %}" class="btn">
Preferences
</a>
</span>
</h2>
<h3 class="padded">Summary</h3>
<div class="row-fluid padded">
<div class="padded span6">
{% with categories|length as num_categories %}
Watching {{ num_categories }} categor{{ num_categories|pluralize:"y,ies"}}
<ul>
<li>{{ categories_upstream }} new upstream version{{ categories_upstream|pluralize:"s"}}</li>
{% if categories_upstream %}
<li>
Hot categories:
<ul>
{% for c in categories|slice:":3" %}
<li><a href="{% url "category" c.category %}">{{ c.category }}</a> ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
{% endwith %}
</div>
<div class="padded span6">
{% with herds|length as num_herds %}
Watching {{ num_herds }} herd{{ num_herds|pluralize:"s"}}
<ul>
<li>{{ herds_upstream }} new upstream version{{ herds_upstream|pluralize:"s"}}</li>
{% if herds_upstream %}
<li>
Hot herds:
<ul>
{% for c in herds|slice:":3" %}
<li><a href="{% url "herd" c.herds__herd %}">{{ c.herds__herd }}</a> ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
{% endwith %}
</div>
</div>
<div class="padded row-fluid">
<div class="padded span6">
{% with maintainers|length as num_maintainers %}
Watching {{ num_maintainers }} maintainer{{ num_maintainers|pluralize:"s"}}
<ul>
<li>{{ maintainers_upstream }} new upstream version{{ maintainers_upstream|pluralize:"s"}}</li>
{% if maintainers_upstream %}
<li>
Hot maintainers:
<ul>
{% for c in maintainers|slice:":3" %}
<li><a href="{% url "maintainer" c.maintainers__email %}">{{ c.maintainers__name }}</a> ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
{% endwith %}
</div>
<div class="padded span6">
{% with packages|length as num_packages %}
Watching {{ num_packages }} package{{ num_packages|pluralize:"s"}}
<ul>
<li>{{ packages_upstream }} new upstream version{{ packages_upstream|pluralize:"s"}}</li>
{% if packages_upstream %}
<li>
Hot packages:
<ul>
{% for c in packages|slice:":3" %}
<li><a href="{% url "package" c.category c.name %}">{{ c }}</a> ({{ c.n_versions|sub:c.n_packaged|sub:c.n_overlay }})</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
{% endwith %}
</div>
</div>
<dl>
{% include "euscan/_package_vlogs.html" %}
</dl>
{% endblock %}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,116 @@
{% extends "_base.html" %}
{% load url from future %}
{% block title %}
{{ block.super }} - Edit user preferences for {{ user }}
{% endblock %}
{% block css %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/toggle_buttons.css" media="screen" title="Normal" />
{% endblock %}
{% block javascript %}
{{ block.super }}
<script type="text/javascript" language="javascript" src="{{STATIC_URL}}js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="{{STATIC_URL}}js/jquery.toggle.buttons.js"></script>
{% endblock %}
{% block content %}
{% if updated %}
<div class="alert alert-success">
<strong>Saved!</strong> Your preferences have been saved
</div>
{% endif %}
<h2>
Edit user preferences
</h2>
<form id="preferences_form" method='post' action='.'>
{% csrf_token %}
<table class="table">
<thead><tr><th>Personal settings</th></tr></thead>
<tr>
<th>{{ form.first_name.label_tag }}</th>
<td>{% if form.first_name.errors %}<ul class="errorlist">{{ form.first_name.errors }}</ul>{% endif %}{{ form.first_name }}</td>
</tr>
<tr>
<th>{{ form.last_name.label_tag }}</th>
<td>{% if form.last_name.errors %}<ul class="errorlist">{{ form.last_name.errors }}</ul>{% endif %}{{ form.last_name }}</td>
</tr>
<tr>
<th>{{ form.email.label_tag }}</th>
<td>{% if form.first_name.errors %}<ul class="errorlist">{{ form.email.errors }}</ul>{% endif %} {{ form.email }}</td>
</tr>
</table>
<table class="table">
<thead><tr><th>Feed settings</th></tr></thead>
<tr>
<th>{{ form.feed_upstream_info.label_tag }}</th>
<td>{{ form.feed_upstream_info }}</td>
</tr>
<tr>
<th>{{ form.feed_portage_info.label_tag }}</th>
<td>{{ form.feed_portage_info }}</td>
</tr>
<tr>
<th>{{ form.feed_show_adds.label_tag }}</th>
<td>{{ form.feed_show_adds }}</td>
</tr>
<tr>
<th>{{ form.feed_show_removals.label_tag }}</th>
<td>{{ form.feed_show_removals }}</td>
</tr>
<tr>
<th>{{ form.feed_ignore_pre.label_tag }}</th>
<td>{{ form.feed_ignore_pre }}</td>
</tr>
<tr>
<th>{{ form.feed_ignore_pre_if_stable.label_tag }}</th>
<td>{{ form.feed_ignore_pre_if_stable }}</td>
</tr>
</table>
<table class="table">
<thead><tr><th>Mail settings</th></tr></thead>
<tr>
<th>{{ form.email_activated.label_tag }}</th>
<td>{{ form.email_activated }}</td>
</tr>
<tr>
<th>{{ form.email_every.label_tag }}</th>
<td>{{ form.email_every }}</td>
</tr>
<tr>
<th>{{ form.email_ignore_pre.label_tag }}</th>
<td>{{ form.email_ignore_pre }}</td>
</tr>
<tr>
<th>{{ form.email_ignore_pre_if_stable.label_tag }}</th>
<td>{{ form.email_ignore_pre_if_stable }}</td>
</tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr>
<td></td>
<td>
<input class="btn btn-large" type='submit' value="Save" />
</td>
</tr>
</table>
</form>
<script type="text/javascript">
$(document).ready(function() {
$("#preferences_form").find("input:checkbox").each(function () {
var div = $("<div/>")
, td = $(this).closest("td");
$(this).remove();
td.append(div.append($(this)));
div.toggleButtons();
});
});
</script>
{% endblock %}

View File

@ -0,0 +1,16 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)

View File

@ -0,0 +1,26 @@
from django.conf.urls import patterns, url
from django.contrib.auth.views import logout
from django.views.generic import RedirectView
from django.contrib.auth.decorators import login_required
from euscan_accounts.feeds import UserFeed
urlpatterns = patterns('euscan_accounts.views',
url(r'^profile/$', 'accounts_index', name="accounts_index"),
url(r'^profile/preferences/$', 'accounts_preferences',
name="accounts_preferences"),
url(r'^categories/$', 'accounts_categories', name="accounts_categories"),
url(r'^herds/$', 'accounts_herds', name="accounts_herds"),
url(r'^maintainers/$', 'accounts_maintainers',
name="accounts_maintainers"),
url(r'^packages/$', 'accounts_packages', name="accounts_packages"),
url(r'^overlays/$', 'accounts_overlays', name="accounts_overlays"),
url(r'^feed/$', login_required(UserFeed()), name='user_feed'),
url(r'^logout/$', logout, {'next_page': '/'}),
url(r'^password/change/done/$',
RedirectView.as_view(url="../../../profile/")),
)

View File

@ -0,0 +1,221 @@
from annoying.decorators import render_to, ajax_request
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
from djeuscan.models import Package, Category, Herd, Overlay
from djeuscan.helpers import get_maintainer_or_404
from euscan_accounts.feeds import UserFeed
from euscan_accounts.forms import PreferencesForm
from euscan_accounts.helpers import get_user_fav_infos, get_profile, \
get_account_categories, get_account_herds, get_account_maintainers
@login_required
@render_to('euscan/accounts/index.html')
def accounts_index(request):
user = request.user
infos = get_user_fav_infos(user)
infos['vlog'] = UserFeed().items({'user': user, 'options': {}})
return infos
@login_required
@render_to('euscan/accounts/preferences.html')
def accounts_preferences(request):
user = request.user
prof = get_profile(user)
updated = False
if request.method == "POST":
form = PreferencesForm(request.POST)
if form.is_valid():
user.first_name = form.cleaned_data["first_name"]
user.last_name = form.cleaned_data["last_name"]
user.email = form.cleaned_data["email"]
user.save(force_update=True)
prof.feed_upstream_info = form.cleaned_data["feed_upstream_info"]
prof.feed_portage_info = form.cleaned_data["feed_portage_info"]
prof.feed_show_adds = form.cleaned_data["feed_show_adds"]
prof.feed_show_removals = form.cleaned_data["feed_show_removals"]
prof.feed_ignore_pre = form.cleaned_data["feed_ignore_pre"]
prof.feed_ignore_pre_if_stable = \
form.cleaned_data["feed_ignore_pre_if_stable"]
prof.email_activated = form.cleaned_data["email_activated"]
prof.email_every = form.cleaned_data["email_every"]
prof.email_ignore_pre = form.cleaned_data["email_ignore_pre"]
prof.email_ignore_pre_if_stable = \
form.cleaned_data["email_ignore_pre_if_stable"]
prof.save(force_update=True)
updated = True
else:
initial_data = {
"first_name": user.first_name,
"last_name": user.last_name,
"email": user.email,
"feed_upstream_info": prof.feed_upstream_info,
"feed_portage_info": prof.feed_portage_info,
"feed_show_adds": prof.feed_show_adds,
"feed_show_removals": prof.feed_show_removals,
"feed_ignore_pre": prof.feed_ignore_pre,
"feed_ignore_pre_if_stable": prof.feed_ignore_pre_if_stable,
"email_activated": prof.email_activated,
"email_every": prof.email_every,
"email_ignore_pre": prof.email_ignore_pre,
"email_ignore_pre_if_stable": prof.email_ignore_pre_if_stable,
}
form = PreferencesForm(initial_data)
return {"form": form, "updated": updated}
@login_required
@render_to('euscan/accounts/categories.html')
def accounts_categories(request):
return {"categories": get_account_categories(request.user)}
@login_required
@render_to('euscan/accounts/herds.html')
def accounts_herds(request):
return {"herds": get_account_herds(request.user)}
@login_required
@render_to('euscan/accounts/maintainers.html')
def accounts_maintainers(request):
return {"maintainers": get_account_maintainers(request.user)}
@login_required
@render_to('euscan/accounts/packages.html')
def accounts_packages(request):
return {"packages": get_profile(request.user).packages.all()}
@login_required
@render_to('euscan/accounts/overlays.html')
def accounts_overlays(request):
overlays = [obj.name for obj in get_profile(request.user).overlays.all()]
return {"overlays": overlays}
@login_required
@require_POST
@ajax_request
def favourite_package(request, category, package):
obj = get_object_or_404(Package, category=category, name=package)
get_profile(request.user).packages.add(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def unfavourite_package(request, category, package):
package = get_object_or_404(Package, category=category, name=package)
get_profile(request.user).packages.remove(package)
return {"success": True}
@login_required
@require_POST
@ajax_request
def favourite_herd(request, herd):
obj = get_object_or_404(Herd, herd=herd)
get_profile(request.user).herds.add(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def unfavourite_herd(request, herd):
herd = get_object_or_404(Herd, herd=herd)
get_profile(request.user).herds.remove(herd)
return {"success": True}
@login_required
@require_POST
@ajax_request
def favourite_maintainer(request, maintainer_id=None, maintainer_email=None):
obj = get_maintainer_or_404(maintainer_id, maintainer_email)
get_profile(request.user).maintainers.add(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def unfavourite_maintainer(request, maintainer_id=None, maintainer_email=None):
obj = get_maintainer_or_404(maintainer_id, maintainer_email)
get_profile(request.user).maintainers.remove(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def favourite_category(request, category):
obj = Category.objects.get(name=category)
get_profile(request.user).categories.add(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def unfavourite_category(request, category):
obj = Category.objects.get(name=category)
get_profile(request.user).categories.remove(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def favourite_overlay(request, overlay):
obj = Overlay.objects.get(name=overlay)
get_profile(request.user).overlays.add(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def unfavourite_overlay(request, overlay):
obj = Overlay.objects.get(name=overlay)
get_profile(request.user).overlays.remove(obj)
return {"success": True}
@login_required
@require_POST
@ajax_request
def favourite_world(request):
if not "packages[]" in request.POST:
return {"success": False}
packages = request.POST.getlist("packages[]")
objs = Package.objects.filter(id__in=packages)
get_profile(request.user).packages.add(*objs)
return {"success": True}
@login_required
@require_POST
@ajax_request
def unfavourite_world(request):
if not "packages[]" in request.POST:
return {"success": False}
packages = request.POST.getlist("packages[]")
objs = Package.objects.filter(id__in=packages)
get_profile(request.user).packages.remove(*objs)
return {"success": True}