euscanwww: charts, about, etc...
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
This commit is contained in:
parent
13dd433996
commit
0aba96f66f
115
euscanwww/euscan/charts.py
Normal file
115
euscanwww/euscan/charts.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
|
||||||
|
from euscanwww import settings
|
||||||
|
|
||||||
|
from django.db.models import F, Sum, Max
|
||||||
|
from euscan.models import Version, Package, Herd, Maintainer
|
||||||
|
from euscan.models import CategoryLog
|
||||||
|
|
||||||
|
import pylab
|
||||||
|
import matplotlib
|
||||||
|
|
||||||
|
CHARTS_ROOT = os.path.join(settings.MEDIA_ROOT, "charts")
|
||||||
|
CHARTS_URL = os.path.join(settings.MEDIA_URL, "charts")
|
||||||
|
CHARTS_TTL = (24 * 60 * 60)
|
||||||
|
|
||||||
|
pylab.rcParams['font.size'] = 10.0
|
||||||
|
pylab.rcParams['axes.titlesize'] = 10.0
|
||||||
|
pylab.rcParams['xtick.labelsize'] = 8.0
|
||||||
|
pylab.rcParams['legend.fontsize'] = 8.0
|
||||||
|
|
||||||
|
def xint(i):
|
||||||
|
try:
|
||||||
|
return int(i)
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def chart_alive(name):
|
||||||
|
path = os.path.join(CHARTS_ROOT, name)
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return False
|
||||||
|
if os.path.getmtime(__file__) > os.path.getmtime(path):
|
||||||
|
return False
|
||||||
|
if os.path.getmtime(path) + CHARTS_TTL < time.time():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def chart_name(name, **kwargs):
|
||||||
|
if 'category' in kwargs and kwargs['category']:
|
||||||
|
name += '-%s' % kwargs['category']
|
||||||
|
if 'herd' in kwargs and kwargs['herd']:
|
||||||
|
name += '-h-%d' % kwargs['herd'].id
|
||||||
|
if 'maintainer' in kwargs and kwargs['maintainer']:
|
||||||
|
name += '-m-%d' % kwargs['maintainer'].id
|
||||||
|
return name + ".png"
|
||||||
|
|
||||||
|
def packages(**kwargs):
|
||||||
|
packages = Package.objects
|
||||||
|
|
||||||
|
if 'category' in kwargs and kwargs['category']:
|
||||||
|
packages = packages.filter(category=kwargs['category'])
|
||||||
|
if 'herd' in kwargs and kwargs['herd']:
|
||||||
|
packages = packages.filter(herds__id=kwargs['herd'].id)
|
||||||
|
if 'maintainer' in kwargs and kwargs['maintainer']:
|
||||||
|
packages = packages.filter(maintainers__id=kwargs['maintainer'].id)
|
||||||
|
|
||||||
|
return packages
|
||||||
|
|
||||||
|
def cached_pylab_chart(f):
|
||||||
|
def new_f(*args, **kwds):
|
||||||
|
name = chart_name(f.func_name, **kwds)
|
||||||
|
|
||||||
|
if not chart_alive(name):
|
||||||
|
f(*args, **kwds)
|
||||||
|
pylab.savefig(os.path.join(CHARTS_ROOT, name))
|
||||||
|
pylab.close()
|
||||||
|
|
||||||
|
return name
|
||||||
|
|
||||||
|
new_f.func_name = f.func_name
|
||||||
|
return new_f
|
||||||
|
|
||||||
|
@cached_pylab_chart
|
||||||
|
def pie_versions(**kwargs):
|
||||||
|
n_packaged = xint(packages(**kwargs).aggregate(Sum('n_packaged'))['n_packaged__sum'])
|
||||||
|
n_overlay = xint(packages(**kwargs).aggregate(Sum('n_overlay'))['n_overlay__sum'])
|
||||||
|
n_versions = xint(packages(**kwargs).aggregate(Sum('n_versions'))['n_versions__sum'])
|
||||||
|
n_upstream = n_versions - n_packaged - n_overlay
|
||||||
|
|
||||||
|
pylab.figure(1, figsize=(3.5,3.5))
|
||||||
|
|
||||||
|
if n_overlay:
|
||||||
|
labels = 'Gentoo', 'Overlays', 'Upstream'
|
||||||
|
fracs = [n_packaged, n_overlay, n_upstream]
|
||||||
|
colors = '#008000', '#0B17FD', '#FF0000'
|
||||||
|
else:
|
||||||
|
labels = 'Gentoo', 'Upstream'
|
||||||
|
fracs = [n_packaged, n_upstream]
|
||||||
|
colors = '#008000', '#FF0000'
|
||||||
|
|
||||||
|
pylab.pie(fracs, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True)
|
||||||
|
pylab.title('Versions', bbox={'facecolor':'0.8', 'pad':5})
|
||||||
|
|
||||||
|
@cached_pylab_chart
|
||||||
|
def pie_packages(**kwargs):
|
||||||
|
n_packages = packages(**kwargs).count()
|
||||||
|
n_packages_uptodate_main = packages(**kwargs).filter(n_versions=F('n_packaged')).count()
|
||||||
|
n_packages_uptodate_all = packages(**kwargs).filter(n_versions=F('n_packaged') + F('n_overlay')).count()
|
||||||
|
n_packages_outdated = n_packages - n_packages_uptodate_all
|
||||||
|
n_packages_uptodate_ovl = n_packages_uptodate_all - n_packages_uptodate_main
|
||||||
|
|
||||||
|
pylab.figure(1, figsize=(3.5,3.5))
|
||||||
|
|
||||||
|
if n_packages_uptodate_ovl:
|
||||||
|
labels = 'Ok (gentoo)', 'Ok (overlays)', 'Outdated'
|
||||||
|
fracs = [n_packages_uptodate_main, n_packages_uptodate_ovl, n_packages_outdated]
|
||||||
|
colors = '#008000', '#0B17FD', '#FF0000'
|
||||||
|
else:
|
||||||
|
labels = 'Ok (gentoo)', 'Outdated'
|
||||||
|
fracs = [n_packages_uptodate_main, n_packages_outdated]
|
||||||
|
colors = '#008000', '#FF0000'
|
||||||
|
|
||||||
|
pylab.pie(fracs, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True)
|
||||||
|
pylab.title('Packages', bbox={'facecolor':'0.8', 'pad':5})
|
||||||
|
|
@ -62,7 +62,7 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
matches = sorted(matches)
|
matches = sorted(matches)
|
||||||
pkg = matches.pop()
|
pkg = matches.pop()
|
||||||
if pkg.version == '9999' and len(matches):
|
if '9999' in pkg.version and len(matches):
|
||||||
pkg = matches.pop()
|
pkg = matches.pop()
|
||||||
|
|
||||||
obj, created = Package.objects.get_or_create(category=pkg.category, name=pkg.name)
|
obj, created = Package.objects.get_or_create(category=pkg.category, name=pkg.name)
|
||||||
|
@ -103,14 +103,14 @@ class Command(BaseCommand):
|
|||||||
slot = match.group('slot')
|
slot = match.group('slot')
|
||||||
overlay = match.group('overlay')
|
overlay = match.group('overlay')
|
||||||
|
|
||||||
if not package or not cpv.startswith(str(package)):
|
cat, pkg, ver, rev = portage.catpkgsplit(cpv)
|
||||||
package = self.store_package(options, cpv)
|
|
||||||
|
if not package or not (cat == package.category and pkg == package.name):
|
||||||
|
package = self.store_package(options, cat, pkg)
|
||||||
|
|
||||||
self.store_version(options, package, cpv, slot, overlay)
|
self.store_version(options, package, cpv, slot, overlay)
|
||||||
|
|
||||||
def store_package(self, options, cpv):
|
def store_package(self, options, cat, pkg):
|
||||||
cat, pkg, ver, rev = portage.catpkgsplit(cpv)
|
|
||||||
|
|
||||||
obj, created = Package.objects.get_or_create(category=cat, name=pkg)
|
obj, created = Package.objects.get_or_create(category=cat, name=pkg)
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
@ -121,6 +121,7 @@ class Command(BaseCommand):
|
|||||||
Version.objects.filter(package=obj, packaged=True).delete()
|
Version.objects.filter(package=obj, packaged=True).delete()
|
||||||
|
|
||||||
obj.n_packaged = 0
|
obj.n_packaged = 0
|
||||||
|
obj.n_overlay = 0
|
||||||
obj.n_versions = Version.objects.filter(package=obj).count()
|
obj.n_versions = Version.objects.filter(package=obj).count()
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
@ -144,7 +145,10 @@ class Command(BaseCommand):
|
|||||||
overlay=overlay)
|
overlay=overlay)
|
||||||
|
|
||||||
if created or not package.n_packaged:
|
if created or not package.n_packaged:
|
||||||
|
if overlay == 'gentoo':
|
||||||
package.n_packaged += 1
|
package.n_packaged += 1
|
||||||
|
else:
|
||||||
|
package.n_overlay += 1
|
||||||
if created:
|
if created:
|
||||||
package.n_versions += 1
|
package.n_versions += 1
|
||||||
|
|
||||||
|
@ -51,40 +51,44 @@ class Command(BaseCommand):
|
|||||||
for package in Package.objects.all():
|
for package in Package.objects.all():
|
||||||
# Should not be needed, but can't hurt
|
# Should not be needed, but can't hurt
|
||||||
package.n_versions = Version.objects.filter(package=package).count()
|
package.n_versions = Version.objects.filter(package=package).count()
|
||||||
package.n_packaged != Version.objects.filter(package=package,packaged=True).count()
|
package.n_packaged = Version.objects.filter(package=package, packaged=True, overlay='gentoo').count()
|
||||||
|
package.n_overlay = Version.objects.filter(package=package, packaged=True).exclude(overlay='gentoo').count()
|
||||||
package.save()
|
package.save()
|
||||||
|
|
||||||
for herd in package.herds.all():
|
for herd in package.herds.all():
|
||||||
herds[herd].n_packages += 1
|
herds[herd].n_packages += 1
|
||||||
herds[herd].n_versions += package.n_versions
|
herds[herd].n_versions += package.n_versions
|
||||||
herds[herd].n_packaged += package.n_packaged
|
herds[herd].n_packaged += package.n_packaged
|
||||||
|
herds[herd].n_overlay += package.n_overlay
|
||||||
|
|
||||||
for maintainer in package.maintainers.all():
|
for maintainer in package.maintainers.all():
|
||||||
maintainers[maintainer].n_packages += 1
|
maintainers[maintainer].n_packages += 1
|
||||||
maintainers[maintainer].n_versions += package.n_versions
|
maintainers[maintainer].n_versions += package.n_versions
|
||||||
maintainers[maintainer].n_packaged += package.n_packaged
|
maintainers[maintainer].n_packaged += package.n_packaged
|
||||||
|
maintainers[maintainer].n_overlay += package.n_overlay
|
||||||
|
|
||||||
categories[package.category].n_packages += 1
|
categories[package.category].n_packages += 1
|
||||||
categories[package.category].n_versions += package.n_versions
|
categories[package.category].n_versions += package.n_versions
|
||||||
categories[package.category].n_packaged += package.n_packaged
|
categories[package.category].n_packaged += package.n_packaged
|
||||||
|
categories[package.category].n_overlay += package.n_overlay
|
||||||
|
|
||||||
for clog in categories.values():
|
for clog in categories.values():
|
||||||
if not options['quiet']:
|
if not options['quiet']:
|
||||||
self.stdout.write('[c] %s - [%d, %d/%d]\n' %
|
self.stdout.write('[c] %s - [%d, %d/%d/%d]\n' %
|
||||||
(clog.category, clog.n_packages,
|
(clog.category, clog.n_packages,
|
||||||
clog.n_packaged, clog.n_versions))
|
clog.n_packaged, clog.n_overlay, clog.n_versions))
|
||||||
clog.save()
|
clog.save()
|
||||||
|
|
||||||
for hlog in herds.values():
|
for hlog in herds.values():
|
||||||
if not options['quiet']:
|
if not options['quiet']:
|
||||||
self.stdout.write('[h] %s - [%d, %d/%d]\n' %
|
self.stdout.write('[h] %s - [%d, %d/%d/%d]\n' %
|
||||||
(hlog.herd, hlog.n_packages,
|
(hlog.herd, hlog.n_packages,
|
||||||
hlog.n_packaged, hlog.n_versions))
|
hlog.n_packaged, hlog.n_overlay, hlog.n_versions))
|
||||||
hlog.save()
|
hlog.save()
|
||||||
|
|
||||||
for mlog in maintainers.values():
|
for mlog in maintainers.values():
|
||||||
if not options['quiet']:
|
if not options['quiet']:
|
||||||
self.stdout.write('[m] %s - [%d, %d/%d]\n' %
|
self.stdout.write('[m] %s - [%d, %d/%d/%d]\n' %
|
||||||
(mlog.maintainer, mlog.n_packages,
|
(mlog.maintainer, mlog.n_packages,
|
||||||
mlog.n_packaged, mlog.n_versions))
|
mlog.n_packaged, mlog.n_overlay, mlog.n_versions))
|
||||||
mlog.save()
|
mlog.save()
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
# 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 'CategoryLog.n_overlay'
|
||||||
|
db.add_column('euscan_categorylog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
|
||||||
|
|
||||||
|
# Adding field 'Package.n_overlay'
|
||||||
|
db.add_column('euscan_package', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
|
||||||
|
|
||||||
|
# Adding field 'HerdLog.n_overlay'
|
||||||
|
db.add_column('euscan_herdlog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
|
||||||
|
|
||||||
|
# Adding field 'MaintainerLog.n_overlay'
|
||||||
|
db.add_column('euscan_maintainerlog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
|
||||||
|
|
||||||
|
|
||||||
|
def backwards(self, orm):
|
||||||
|
|
||||||
|
# Deleting field 'CategoryLog.n_overlay'
|
||||||
|
db.delete_column('euscan_categorylog', 'n_overlay')
|
||||||
|
|
||||||
|
# Deleting field 'Package.n_overlay'
|
||||||
|
db.delete_column('euscan_package', 'n_overlay')
|
||||||
|
|
||||||
|
# Deleting field 'HerdLog.n_overlay'
|
||||||
|
db.delete_column('euscan_herdlog', 'n_overlay')
|
||||||
|
|
||||||
|
# Deleting field 'MaintainerLog.n_overlay'
|
||||||
|
db.delete_column('euscan_maintainerlog', 'n_overlay')
|
||||||
|
|
||||||
|
|
||||||
|
models = {
|
||||||
|
'euscan.categorylog': {
|
||||||
|
'Meta': {'object_name': 'CategoryLog'},
|
||||||
|
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||||
|
},
|
||||||
|
'euscan.euscanresult': {
|
||||||
|
'Meta': {'object_name': 'EuscanResult'},
|
||||||
|
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
|
||||||
|
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||||
|
},
|
||||||
|
'euscan.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'})
|
||||||
|
},
|
||||||
|
'euscan.herdlog': {
|
||||||
|
'Meta': {'object_name': 'HerdLog'},
|
||||||
|
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
|
||||||
|
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||||
|
},
|
||||||
|
'euscan.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'})
|
||||||
|
},
|
||||||
|
'euscan.maintainerlog': {
|
||||||
|
'Meta': {'object_name': 'MaintainerLog'},
|
||||||
|
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"}),
|
||||||
|
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||||
|
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
|
||||||
|
},
|
||||||
|
'euscan.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['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||||
|
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.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'})
|
||||||
|
},
|
||||||
|
'euscan.version': {
|
||||||
|
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
|
||||||
|
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||||
|
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
|
||||||
|
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
|
||||||
|
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||||
|
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||||
|
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||||
|
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
complete_apps = ['euscan']
|
@ -27,6 +27,7 @@ class Package(models.Model):
|
|||||||
# For performance, we keep pre-computed counters
|
# For performance, we keep pre-computed counters
|
||||||
n_versions = models.IntegerField(default=0)
|
n_versions = models.IntegerField(default=0)
|
||||||
n_packaged = models.IntegerField(default=0)
|
n_packaged = models.IntegerField(default=0)
|
||||||
|
n_overlay = models.IntegerField(default=0)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return '%s/%s' % (self.category, self.name)
|
return '%s/%s' % (self.category, self.name)
|
||||||
@ -40,7 +41,7 @@ class Version(models.Model):
|
|||||||
revision = models.CharField(max_length=128)
|
revision = models.CharField(max_length=128)
|
||||||
version = models.CharField(max_length=128)
|
version = models.CharField(max_length=128)
|
||||||
packaged = models.BooleanField()
|
packaged = models.BooleanField()
|
||||||
overlay = models.CharField(max_length=128)
|
overlay = models.CharField(max_length=128, default='gentoo')
|
||||||
urls = models.TextField(blank=True)
|
urls = models.TextField(blank=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
@ -64,6 +65,7 @@ class CategoryLog(models.Model):
|
|||||||
n_packages = models.IntegerField(default=0)
|
n_packages = models.IntegerField(default=0)
|
||||||
n_versions = models.IntegerField(default=0)
|
n_versions = models.IntegerField(default=0)
|
||||||
n_packaged = models.IntegerField(default=0)
|
n_packaged = models.IntegerField(default=0)
|
||||||
|
n_overlay = models.IntegerField(default=0)
|
||||||
|
|
||||||
class HerdLog(models.Model):
|
class HerdLog(models.Model):
|
||||||
herd = models.ForeignKey(Herd)
|
herd = models.ForeignKey(Herd)
|
||||||
@ -72,6 +74,7 @@ class HerdLog(models.Model):
|
|||||||
n_packages = models.IntegerField(default=0)
|
n_packages = models.IntegerField(default=0)
|
||||||
n_versions = models.IntegerField(default=0)
|
n_versions = models.IntegerField(default=0)
|
||||||
n_packaged = models.IntegerField(default=0)
|
n_packaged = models.IntegerField(default=0)
|
||||||
|
n_overlay = models.IntegerField(default=0)
|
||||||
|
|
||||||
class MaintainerLog(models.Model):
|
class MaintainerLog(models.Model):
|
||||||
maintainer = models.ForeignKey(Maintainer)
|
maintainer = models.ForeignKey(Maintainer)
|
||||||
@ -80,3 +83,4 @@ class MaintainerLog(models.Model):
|
|||||||
n_packages = models.IntegerField(default=0)
|
n_packages = models.IntegerField(default=0)
|
||||||
n_versions = models.IntegerField(default=0)
|
n_versions = models.IntegerField(default=0)
|
||||||
n_packaged = models.IntegerField(default=0)
|
n_packaged = models.IntegerField(default=0)
|
||||||
|
n_overlay = models.IntegerField(default=0)
|
||||||
|
8
euscanwww/euscan/templatetags/div.py
Normal file
8
euscanwww/euscan/templatetags/div.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from django import template
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
def div(value, arg=None):
|
||||||
|
return value/arg
|
||||||
|
|
||||||
|
register.filter('div', div)
|
@ -5,3 +5,11 @@ register = template.Library()
|
|||||||
@register.inclusion_tag('euscan/_packages.html')
|
@register.inclusion_tag('euscan/_packages.html')
|
||||||
def packages(packages):
|
def packages(packages):
|
||||||
return { 'packages' : packages }
|
return { 'packages' : packages }
|
||||||
|
|
||||||
|
@register.inclusion_tag('euscan/_package_cols.html')
|
||||||
|
def package_cols(infos):
|
||||||
|
return { 'infos' : infos }
|
||||||
|
|
||||||
|
@register.inclusion_tag('euscan/_package_bar.html')
|
||||||
|
def package_bar(infos):
|
||||||
|
return { 'infos' : infos }
|
||||||
|
@ -2,14 +2,19 @@ from django.conf.urls.defaults import *
|
|||||||
|
|
||||||
urlpatterns = patterns('euscan.views',
|
urlpatterns = patterns('euscan.views',
|
||||||
(r'^$', 'index'),
|
(r'^$', 'index'),
|
||||||
(r'^logs/$', 'logs'),
|
(r'^about/$', 'about'),
|
||||||
|
(r'^statistics/$', 'statistics'),
|
||||||
|
(r'^statistics/charts/(?P<chart>[\w\-]+).png$', 'chart'),
|
||||||
(r'^world/$', 'world'),
|
(r'^world/$', 'world'),
|
||||||
(r'^world/scan/$', 'world_scan'),
|
(r'^world/scan/$', 'world_scan'),
|
||||||
(r'^categories/$', 'categories'),
|
(r'^categories/$', 'categories'),
|
||||||
(r'^categories/(?P<category>[\w+][\w+.-]*)/view/$', 'category'),
|
(r'^categories/(?P<category>[\w+][\w+.-]*)/view/$', 'category'),
|
||||||
|
(r'^categories/(?P<category>[\w+][\w+.-]*)/charts/(?P<chart>[\w\-]+).png$', 'chart_category'),
|
||||||
(r'^herds/$', 'herds'),
|
(r'^herds/$', 'herds'),
|
||||||
(r'^herds/(?P<herd>[\{\}\w+.-]*)/view/$', 'herd'),
|
(r'^herds/(?P<herd>[\{\}\w+.-]*)/view/$', 'herd'),
|
||||||
|
(r'^herds/(?P<herd>[\{\}\w+.-]*)/charts/(?P<chart>[\w\-]+).png$', 'chart_herd'),
|
||||||
(r'^maintainers/$', 'maintainers'),
|
(r'^maintainers/$', 'maintainers'),
|
||||||
(r'^maintainers/(?P<maintainer_id>\d+)/view/$', 'maintainer'),
|
(r'^maintainers/(?P<maintainer_id>\d+)/view/$', 'maintainer'),
|
||||||
|
(r'^maintainers/(?P<maintainer_id>\d+)/charts/(?P<chart>[\w\-]+).png$', 'chart_maintainer'),
|
||||||
(r'^package/(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/$', 'package'),
|
(r'^package/(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/$', 'package'),
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from annoying.decorators import render_to
|
from annoying.decorators import render_to
|
||||||
|
from django.http import HttpResponse
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.db.models import Sum, Max
|
from django.db.models import Sum, Max
|
||||||
@ -6,13 +7,17 @@ from django.db.models import Sum, Max
|
|||||||
from euscan.models import Version, Package, Herd, Maintainer, EuscanResult
|
from euscan.models import Version, Package, Herd, Maintainer, EuscanResult
|
||||||
from euscan.forms import WorldForm, PackagesForm
|
from euscan.forms import WorldForm, PackagesForm
|
||||||
|
|
||||||
|
import charts
|
||||||
|
|
||||||
|
""" Views """
|
||||||
|
|
||||||
@render_to('euscan/index.html')
|
@render_to('euscan/index.html')
|
||||||
def index(request):
|
def index(request):
|
||||||
ctx = {}
|
ctx = {}
|
||||||
ctx['n_packaged'] = Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum']
|
ctx['n_packaged'] = charts.xint(Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum'])
|
||||||
ctx['n_versions'] = Package.objects.aggregate(Sum('n_versions'))['n_versions__sum']
|
ctx['n_overlay'] = charts.xint(Package.objects.aggregate(Sum('n_overlay'))['n_overlay__sum'])
|
||||||
if ctx['n_versions'] is not None and ctx['n_packaged'] is not None:
|
ctx['n_versions'] = charts.xint(Package.objects.aggregate(Sum('n_versions'))['n_versions__sum'])
|
||||||
ctx['n_upstream'] = ctx['n_versions'] - ctx['n_packaged']
|
ctx['n_upstream'] = ctx['n_versions'] - ctx['n_packaged'] - ctx['n_overlay']
|
||||||
ctx['n_packages'] = Package.objects.count()
|
ctx['n_packages'] = Package.objects.count()
|
||||||
ctx['n_herds'] = Herd.objects.count()
|
ctx['n_herds'] = Herd.objects.count()
|
||||||
ctx['n_maintainers'] = Maintainer.objects.count()
|
ctx['n_maintainers'] = Maintainer.objects.count()
|
||||||
@ -25,7 +30,10 @@ def logs(request):
|
|||||||
|
|
||||||
@render_to('euscan/categories.html')
|
@render_to('euscan/categories.html')
|
||||||
def categories(request):
|
def categories(request):
|
||||||
categories = Package.objects.values('category').annotate(n_packaged=Sum('n_packaged'), n_versions=Sum('n_versions'))
|
categories = Package.objects.values('category').annotate(n_packaged=Sum('n_packaged'),
|
||||||
|
n_overlay=Sum('n_overlay'),
|
||||||
|
n_versions=Sum('n_versions'))
|
||||||
|
|
||||||
return { 'categories' : categories }
|
return { 'categories' : categories }
|
||||||
|
|
||||||
@render_to('euscan/category.html')
|
@render_to('euscan/category.html')
|
||||||
@ -38,7 +46,10 @@ def category(request, category):
|
|||||||
@render_to('euscan/herds.html')
|
@render_to('euscan/herds.html')
|
||||||
def herds(request):
|
def herds(request):
|
||||||
# FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of 'INNER JOIN'
|
# FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of 'INNER JOIN'
|
||||||
herds = Package.objects.filter(herds__isnull=False).values('herds__herd').annotate(n_packaged=Sum('n_packaged'), n_versions=Sum('n_versions'))
|
herds = Package.objects.filter(herds__isnull=False)
|
||||||
|
herds = herds.values('herds__herd').annotate(n_packaged=Sum('n_packaged'),
|
||||||
|
n_overlay=Sum('n_overlay'),
|
||||||
|
n_versions=Sum('n_versions'))
|
||||||
return { 'herds' : herds }
|
return { 'herds' : herds }
|
||||||
|
|
||||||
@render_to('euscan/herd.html')
|
@render_to('euscan/herd.html')
|
||||||
@ -49,7 +60,12 @@ def herd(request, herd):
|
|||||||
|
|
||||||
@render_to('euscan/maintainers.html')
|
@render_to('euscan/maintainers.html')
|
||||||
def maintainers(request):
|
def maintainers(request):
|
||||||
maintainers = Package.objects.filter(maintainers__isnull=False).values('maintainers__id', 'maintainers__name').annotate(n_packaged=Sum('n_packaged'), n_versions=Sum('n_versions'))
|
maintainers = Package.objects.filter(maintainers__isnull=False)
|
||||||
|
maintainers = maintainers.values('maintainers__id', 'maintainers__name')
|
||||||
|
maintainers = maintainers.annotate(n_packaged=Sum('n_packaged'),
|
||||||
|
n_overlay=Sum('n_overlay'),
|
||||||
|
n_versions=Sum('n_versions'))
|
||||||
|
|
||||||
return { 'maintainers' : maintainers }
|
return { 'maintainers' : maintainers }
|
||||||
|
|
||||||
@render_to('euscan/maintainer.html')
|
@render_to('euscan/maintainer.html')
|
||||||
@ -61,6 +77,7 @@ def maintainer(request, maintainer_id):
|
|||||||
@render_to('euscan/package.html')
|
@render_to('euscan/package.html')
|
||||||
def package(request, category, package):
|
def package(request, category, package):
|
||||||
package = get_object_or_404(Package, category=category, name=package)
|
package = get_object_or_404(Package, category=category, name=package)
|
||||||
|
package.homepages = package.homepage.split(' ')
|
||||||
packaged = Version.objects.filter(package=package, packaged=True)
|
packaged = Version.objects.filter(package=package, packaged=True)
|
||||||
upstream = Version.objects.filter(package=package, packaged=False)
|
upstream = Version.objects.filter(package=package, packaged=False)
|
||||||
log = EuscanResult.objects.filter(package=package).order_by('-datetime')[:1]
|
log = EuscanResult.objects.filter(package=package).order_by('-datetime')[:1]
|
||||||
@ -99,8 +116,42 @@ def world_scan(request):
|
|||||||
packages.extend(Package.objects.filter(name=pkg))
|
packages.extend(Package.objects.filter(name=pkg))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
print packages
|
|
||||||
|
|
||||||
return { 'packages' : packages }
|
return { 'packages' : packages }
|
||||||
|
|
||||||
|
|
||||||
|
@render_to("euscan/about.html")
|
||||||
|
def about(request):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@render_to("euscan/statistics.html")
|
||||||
|
def statistics(request):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def chart(request, **kwargs):
|
||||||
|
from django.views.static import serve
|
||||||
|
|
||||||
|
chart = kwargs['chart'] if 'chart' in kwargs else None
|
||||||
|
|
||||||
|
if 'maintainer_id' in kwargs:
|
||||||
|
kwargs['maintainer'] = get_object_or_404(Maintainer, id=kwargs['maintainer_id'])
|
||||||
|
if 'herd' in kwargs:
|
||||||
|
kwargs['herd'] = get_object_or_404(Herd, herd=kwargs['herd'])
|
||||||
|
|
||||||
|
if chart == 'pie-packages':
|
||||||
|
path = charts.pie_packages(**kwargs)
|
||||||
|
elif chart == 'pie-versions':
|
||||||
|
path = charts.pie_versions(**kwargs)
|
||||||
|
else:
|
||||||
|
raise Http404()
|
||||||
|
|
||||||
|
return serve(request, path, document_root=charts.CHARTS_ROOT)
|
||||||
|
|
||||||
|
def chart_maintainer(request, **kwargs):
|
||||||
|
return chart(request, **kwargs)
|
||||||
|
|
||||||
|
def chart_herd(request, **kwargs):
|
||||||
|
return chart(request, **kwargs)
|
||||||
|
|
||||||
|
def chart_category(request, **kwargs):
|
||||||
|
return chart(request, **kwargs)
|
||||||
|
0
euscanwww/media/charts/.keep_git
Normal file
0
euscanwww/media/charts/.keep_git
Normal file
@ -148,10 +148,6 @@ h1 {
|
|||||||
color:#15B100;
|
color:#15B100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bad {
|
|
||||||
color:#FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr
|
hr
|
||||||
{
|
{
|
||||||
margin: 0.3em 1em 0.3em 1em;
|
margin: 0.3em 1em 0.3em 1em;
|
||||||
@ -230,3 +226,26 @@ th
|
|||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.package_stat {
|
||||||
|
width: 40px;
|
||||||
|
float: right;
|
||||||
|
height: 5px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package_stat div {
|
||||||
|
float: left;
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package_stat .packaged {
|
||||||
|
background: #85ACFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package_stat .overlay {
|
||||||
|
background: #C6D9FD;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package_stat .upstream {
|
||||||
|
background: #FDEADD;
|
||||||
|
}
|
@ -184,20 +184,12 @@ table.display td.center {
|
|||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* DataTables row classes
|
* DataTables row classes
|
||||||
*/
|
*/
|
||||||
table.display tr.gradeA {
|
table.display td.bad {
|
||||||
background-color: #ddffdd;
|
background-color: #FFDFDF;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.display tr.gradeC {
|
table.display td.ugly {
|
||||||
background-color: #ddddff;
|
background-color: #EDB9B9;
|
||||||
}
|
|
||||||
|
|
||||||
table.display tr.gradeX {
|
|
||||||
background-color: #ffdddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.display tr.gradeU {
|
|
||||||
background-color: #ddd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr {
|
tr {
|
||||||
@ -335,22 +327,6 @@ table.KeyTable td.focus {
|
|||||||
border: 3px solid #3366FF;
|
border: 3px solid #3366FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.display tr.gradeA {
|
|
||||||
background-color: #eeffee;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.display tr.gradeC {
|
|
||||||
background-color: #ddddff;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.display tr.gradeX {
|
|
||||||
background-color: #ffdddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.display tr.gradeU {
|
|
||||||
background-color: #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.box {
|
div.box {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
BIN
euscanwww/media/img/django.png
Normal file
BIN
euscanwww/media/img/django.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
euscanwww/media/img/python.png
Normal file
BIN
euscanwww/media/img/python.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
@ -106,5 +106,6 @@ INSTALLED_APPS = (
|
|||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
# Uncomment the next line to enable admin documentation:
|
# Uncomment the next line to enable admin documentation:
|
||||||
# 'django.contrib.admindocs',
|
# 'django.contrib.admindocs',
|
||||||
|
'GChartWrapper.charts'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,26 +25,23 @@
|
|||||||
<li><a href="{% url euscan.views.categories %}">Categories</a></li>
|
<li><a href="{% url euscan.views.categories %}">Categories</a></li>
|
||||||
<li><a href="{% url euscan.views.herds %}">Herds</a></li>
|
<li><a href="{% url euscan.views.herds %}">Herds</a></li>
|
||||||
<li><a href="{% url euscan.views.maintainers %}">Maintainers</a></li>
|
<li><a href="{% url euscan.views.maintainers %}">Maintainers</a></li>
|
||||||
<li><a href="{% url euscan.views.world %}">World</a></li>
|
<li><a href="{% url euscan.views.world %}">Scan World</a></li>
|
||||||
|
<li><a href="{% url euscan.views.statistics %}">Statistics</a></li>
|
||||||
|
<!--
|
||||||
<li>---</li>
|
<li>---</li>
|
||||||
<li><a href="#">Login</a></li>
|
<li><a href="#">Login</a></li>
|
||||||
<li><a href="#">Register</a></li>
|
<li><a href="#">Register</a></li>
|
||||||
|
-->
|
||||||
<li>---</li>
|
<li>---</li>
|
||||||
<li><a href="#">About</a></li>
|
<li><a href="{% url euscan.views.about %}">About</a></li>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
Powered by:
|
Questions, Comments, Corrections ?
|
||||||
<a href="http://kernel.org" titke="Linux Kernel">
|
Email: corentin.chary at gmail.com<br />
|
||||||
<img src="{{MEDIA_URL}}img/linux.png" alt="Linux" />
|
|
||||||
</a>
|
|
||||||
<a href="http://gentoo.org" title="Gentoo">
|
|
||||||
<img src="{{MEDIA_URL}}img/gentoo.png" alt="Gentoo Linux" />
|
|
||||||
</a>
|
|
||||||
-
|
|
||||||
Copyright (C) 2011 <strong>Corentin Chary</strong>
|
Copyright (C) 2011 <strong>Corentin Chary</strong>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
9
euscanwww/templates/euscan/_package_bar.html
Normal file
9
euscanwww/templates/euscan/_package_bar.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% load mul %}
|
||||||
|
{% load sub %}
|
||||||
|
{% load div %}
|
||||||
|
|
||||||
|
<div class="package_stat">
|
||||||
|
<div class="packaged" style="width: {{ infos.n_packaged|mul:100.0|div:infos.n_versions }}%"></div>
|
||||||
|
<div class="overlay" style="width: {{ infos.n_overlay|mul:100.0|div:infos.n_versions }}%"></div>
|
||||||
|
<div class="upstream" style="width: {{ infos.n_versions|sub:infos.n_overlay|sub:infos.n_packaged|mul:100.0|div:infos.n_versions }}%"></div>
|
||||||
|
</div>
|
24
euscanwww/templates/euscan/_package_cols.html
Normal file
24
euscanwww/templates/euscan/_package_cols.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% load packages %}
|
||||||
|
{% load mul %}
|
||||||
|
{% load sub %}
|
||||||
|
{% load div %}
|
||||||
|
|
||||||
|
<td>{{ infos.n_packaged }}</td>
|
||||||
|
{% if infos.n_overlay == 0 or infos.n_overlay <= infos.n_packaged %}
|
||||||
|
<td>
|
||||||
|
{% else %}{% if infos.n_overlay < infos.n_packaged %}
|
||||||
|
<td class="bad">
|
||||||
|
{% else %}
|
||||||
|
<td class="ugly">
|
||||||
|
{% endif %}{% endif %}
|
||||||
|
{{ infos.n_overlay }}
|
||||||
|
</td>
|
||||||
|
{% if infos.n_versions == infos.n_packaged|add:infos.n_overlay %}
|
||||||
|
<td>
|
||||||
|
{% else %}{% if infos.n_versions < infos.n_packaged|add:infos.n_overlay|mul:2 %}
|
||||||
|
<td class="bad">
|
||||||
|
{% else %}
|
||||||
|
<td class="ugly">
|
||||||
|
{% endif %}{% endif %}
|
||||||
|
{{ infos.n_versions|sub:infos.n_packaged|sub:infos.n_overlay }}
|
||||||
|
</td>
|
@ -1,28 +1,22 @@
|
|||||||
{% load sub %}
|
{% load packages %}
|
||||||
{% load mul %}
|
|
||||||
|
|
||||||
<table id="table" class="display">
|
<table id="table" class="display">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Package</th>
|
<th>Package</th>
|
||||||
<th>Ebuilds</th>
|
<th>Gentoo</th>
|
||||||
|
<th>Overlays</th>
|
||||||
<th>Unpackaged</th>
|
<th>Unpackaged</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for package in packages %}
|
{% for package in packages %}
|
||||||
{% if package.n_versions == package.n_packaged %}
|
<tr>
|
||||||
<tr class="gradeA">
|
|
||||||
{% else %}{% if package.n_versions < package.n_packaged|mul:2 %}
|
|
||||||
<tr class="gradeC">
|
|
||||||
{% else %}
|
|
||||||
<tr class="gradeX">
|
|
||||||
{% endif %}{% endif %}
|
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url euscan.views.package package.category package.name %}">
|
<a href="{% url euscan.views.package package.category package.name %}">
|
||||||
{{ package.category }}/{{ package.name }}
|
{{ package.category }}/{{ package.name }}
|
||||||
</a>
|
</a>
|
||||||
|
{% package_bar package %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ package.n_packaged }}</td>
|
{% package_cols package %}
|
||||||
<td>{{ package.n_versions|sub:package.n_packaged }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
37
euscanwww/templates/euscan/about.html
Normal file
37
euscanwww/templates/euscan/about.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% extends "_base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>What's euscan ?</h2>
|
||||||
|
<p>
|
||||||
|
Euscan is both a tool to check if an ebuild is outdated (app-portage/euscan) and a web interface.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This web interface allow you to browse the portage tree, and find outdated ebuilds. It is designed to help maintainers monitor their packages and bump them.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
euscan code source is available at <a href="http://git.iksaif.net/?p=euscan.git;a=summary">http://git.iksaif.net/?p=euscan.git;a=summary</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>This site is not an official Gentoo website.</em>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Copyright (C) 2011 <strong>Corentin Chary</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Powered by:
|
||||||
|
<a href="http://kernel.org" titke="Linux Kernel">
|
||||||
|
<img src="{{MEDIA_URL}}img/linux.png" alt="Linux Kernel" />
|
||||||
|
</a>
|
||||||
|
<a href="http://gentoo.org" title="Gentoo">
|
||||||
|
<img src="{{MEDIA_URL}}img/gentoo.png" alt="Gentoo Linux" />
|
||||||
|
</a>
|
||||||
|
<a href="http://www.djangoproject.com/" title="Django">
|
||||||
|
<img src="{{MEDIA_URL}}img/django.png" alt="Django" />
|
||||||
|
</a>
|
||||||
|
<a href="http://python.org" title="Python">
|
||||||
|
<img src="{{MEDIA_URL}}img/python.png" alt="Python" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
@ -1,7 +1,6 @@
|
|||||||
{% extends "euscan/_datatable.html" %}
|
{% extends "euscan/_datatable.html" %}
|
||||||
|
|
||||||
{% load sub %}
|
{% load packages %}
|
||||||
{% load mul %}
|
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ block.super }} - categories
|
{{ block.super }} - categories
|
||||||
@ -9,24 +8,22 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Categories</h2>
|
<h2>Categories</h2>
|
||||||
|
|
||||||
<table id="table" class="display">
|
<table id="table" class="display">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Category</th>
|
<th>Category</th>
|
||||||
<th>Ebuilds</th>
|
<th>Gentoo</th>
|
||||||
|
<th>Overlays</th>
|
||||||
<th>Unpackaged</th>
|
<th>Unpackaged</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for category in categories %}
|
{% for category in categories %}
|
||||||
{% if category.n_versions == category.n_packaged %}
|
<tr>
|
||||||
<tr class="gradeA">
|
<td>
|
||||||
{% else %}{% if category.n_versions < category.n_packaged|mul:1.5 %}
|
<a href="{% url euscan.views.category category.category %}">{{ category.category }}</a>
|
||||||
<tr class="gradeC">
|
{% package_bar category %}
|
||||||
{% else %}
|
</td>
|
||||||
<tr class="gradeX">
|
{% package_cols category %}
|
||||||
{% endif %}{% endif %}
|
|
||||||
<td><a href="{% url euscan.views.category category.category %}">{{ category.category }}</a></td>
|
|
||||||
<td>{{ category.n_packaged }}</td>
|
|
||||||
<td>{{ category.n_versions|sub:category.n_packaged }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -9,4 +9,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Category: {{ category }}</h2>
|
<h2>Category: {{ category }}</h2>
|
||||||
{% packages packages %}
|
{% packages packages %}
|
||||||
|
|
||||||
|
<h3>Statistics</h2>
|
||||||
|
<h4>Current statistics</h4>
|
||||||
|
<img src="{% url euscan.views.chart_category category 'pie-versions' %}" />
|
||||||
|
<img src="{% url euscan.views.chart_category category 'pie-packages' %}" />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -9,4 +9,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Herd: {{ herd.herd }}</h2>
|
<h2>Herd: {{ herd.herd }}</h2>
|
||||||
{% packages packages %}
|
{% packages packages %}
|
||||||
|
|
||||||
|
<h3>Statistics</h2>
|
||||||
|
<h4>Current statistics</h4>
|
||||||
|
<img src="{% url euscan.views.chart_herd herd.herd 'pie-versions' %}" />
|
||||||
|
<img src="{% url euscan.views.chart_herd herd.herd 'pie-packages' %}" />
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{% extends "euscan/_datatable.html" %}
|
{% extends "euscan/_datatable.html" %}
|
||||||
|
|
||||||
{% load sub %}
|
{% load packages %}
|
||||||
{% load mul %}
|
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ block.super }} - herds
|
{{ block.super }} - herds
|
||||||
@ -12,25 +11,20 @@
|
|||||||
<table id="table" class="display">
|
<table id="table" class="display">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Herd</th>
|
<th>Herd</th>
|
||||||
<th>Ebuilds</th>
|
<th>Gentoo</th>
|
||||||
|
<th>Overlays</th>
|
||||||
<th>Unpackaged</th>
|
<th>Unpackaged</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for herd in herds %}
|
{% for herd in herds %}
|
||||||
{% if herd.n_versions == herd.n_packaged %}
|
<tr>
|
||||||
<tr class="gradeA">
|
|
||||||
{% else %}{% if herd.n_versions < herd.n_packaged|mul:2 %}
|
|
||||||
<tr class="gradeC">
|
|
||||||
{% else %}
|
|
||||||
<tr class="gradeX">
|
|
||||||
{% endif %}{% endif %}
|
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url euscan.views.herd herd.herds__herd %}">
|
<a href="{% url euscan.views.herd herd.herds__herd %}">
|
||||||
{{ herd.herds__herd }}
|
{{ herd.herds__herd }}
|
||||||
</a>
|
</a>
|
||||||
|
{% package_bar herd %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ herd.n_packaged }}</td>
|
{% package_cols herd %}
|
||||||
<td>{{ herd.n_versions|sub:herd.n_packaged }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -8,12 +8,10 @@
|
|||||||
Euscan is both a tool to check if an ebuild is outdated (app-portage/euscan) and a web interface.
|
Euscan is both a tool to check if an ebuild is outdated (app-portage/euscan) and a web interface.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This web interface allow you to browse the portage tree, and find outdated ebuilds. It was designed to help maintainers monitor their packages and bump them.
|
This web interface allow you to browse the portage tree, and find outdated ebuilds. It is designed to help maintainers monitor their packages and bump them.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
euscan code source is available at <a href="http://git.iksaif.net/?p=euscan.git;a=summary">http://git.iksaif.net/?p=euscan.git;a=summary</a>.
|
<h2>Overview</h2>
|
||||||
</p>
|
|
||||||
<h2>Statistics</h2>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Packages: {{ n_packages }}</li>
|
<li>Packages: {{ n_packages }}</li>
|
||||||
<li>Versions: {{ n_packaged }}</li>
|
<li>Versions: {{ n_packaged }}</li>
|
||||||
|
@ -9,4 +9,10 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Maintainer: {{ maintainer.name }} <{{ maintainer.email }}></h2>
|
<h2>Maintainer: {{ maintainer.name }} <{{ maintainer.email }}></h2>
|
||||||
{% packages packages %}
|
{% packages packages %}
|
||||||
|
|
||||||
|
<h3>Statistics</h2>
|
||||||
|
<h4>Current statistics</h4>
|
||||||
|
<img src="{% url euscan.views.chart_maintainer maintainer.id 'pie-versions' %}" />
|
||||||
|
<img src="{% url euscan.views.chart_maintainer maintainer.id 'pie-packages' %}" />
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
{% extends "euscan/_datatable.html" %}
|
{% extends "euscan/_datatable.html" %}
|
||||||
|
|
||||||
{% load sub %}
|
{% load packages %}
|
||||||
{% load mul %}
|
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ block.super }} - maintainers
|
{{ block.super }} - maintainers
|
||||||
@ -12,25 +11,20 @@
|
|||||||
<table id="table" class="display">
|
<table id="table" class="display">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Maintainer</th>
|
<th>Maintainer</th>
|
||||||
<th>Ebuilds</th>
|
<th>Gentoo</th>
|
||||||
|
<th>Overlays</th>
|
||||||
<th>Unpackaged</th>
|
<th>Unpackaged</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for maintainer in maintainers %}
|
{% for maintainer in maintainers %}
|
||||||
{% if maintainer.n_versions == maintainer.n_packaged %}
|
<tr>
|
||||||
<tr class="gradeA">
|
|
||||||
{% else %}{% if maintainer.n_versions < maintainer.n_packaged|mul:2 %}
|
|
||||||
<tr class="gradeC">
|
|
||||||
{% else %}
|
|
||||||
<tr class="gradeX">
|
|
||||||
{% endif %}{% endif %}
|
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url euscan.views.maintainer maintainer.maintainers__id %}">
|
<a href="{% url euscan.views.maintainer maintainer.maintainers__id %}">
|
||||||
{{ maintainer.maintainers__name }}
|
{{ maintainer.maintainers__name }}
|
||||||
</a>
|
</a>
|
||||||
|
{% package_bar maintainer %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ maintainer.n_packaged }}</td>
|
{% package_cols maintainer %}
|
||||||
<td>{{ maintainer.n_versions|sub:maintainer.n_packaged }}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<dt>Homepage</dt>
|
<dt>Homepage</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{% for homepage in package.homepages %}
|
{% for homepage in package.homepages %}
|
||||||
<a href="{{ homepage }}">{{ homepage }}<br />
|
<a href="{{ homepage }}">{{ homepage }}</a><br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dd>
|
</dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
13
euscanwww/templates/euscan/statistics.html
Normal file
13
euscanwww/templates/euscan/statistics.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{% extends "_base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>What's euscan ?</h2>
|
||||||
|
<h2>Statistics</h2>
|
||||||
|
|
||||||
|
<h3>Current statistics</h3>
|
||||||
|
<img src="{% url euscan.views.chart 'pie-versions' %}" />
|
||||||
|
<img src="{% url euscan.views.chart 'pie-packages' %}" />
|
||||||
|
|
||||||
|
<h3>All time statistics</h3>
|
||||||
|
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user