diff options
-rw-r--r-- | README.BRANDING | 2 | ||||
-rw-r--r-- | devel/admin.py | 8 | ||||
-rw-r--r-- | devel/migrations/0002_staffgroup.py | 31 | ||||
-rw-r--r-- | devel/models.py | 37 | ||||
-rw-r--r-- | main/templatetags/flags.py | 2 | ||||
-rw-r--r-- | mirrors/admin.py | 2 | ||||
-rw-r--r-- | mirrors/migrations/0002_mirrorurl_bandwidth.py | 20 | ||||
-rw-r--r-- | mirrors/models.py | 3 | ||||
-rw-r--r-- | mirrors/views.py | 37 | ||||
-rw-r--r-- | public/views.py | 38 | ||||
-rw-r--r-- | settings.py | 5 | ||||
-rw-r--r-- | sitemaps.py | 3 | ||||
-rw-r--r-- | templates/mirrors/mirrors.html | 8 | ||||
-rw-r--r-- | templates/public/developer_list.html | 4 | ||||
-rw-r--r-- | templates/public/index.html | 5 | ||||
-rw-r--r-- | templates/public/userlist.html | 8 | ||||
-rw-r--r-- | urls.py | 10 |
17 files changed, 150 insertions, 73 deletions
diff --git a/README.BRANDING b/README.BRANDING index e75eaeb9..55ef9d91 100644 --- a/README.BRANDING +++ b/README.BRANDING @@ -7,7 +7,7 @@ Files used to configure branding/url stuff ------------------------------------------ * `settings.py` - * `templates/templatetags/package_extras.py` + * `templates/templatetags/jinja2.py` * `main/templatetags/wiki.py` * `main/templatetags/bugs.py` diff --git a/devel/admin.py b/devel/admin.py index c8f80f95..d1729fe3 100644 --- a/devel/admin.py +++ b/devel/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User -from .models import UserProfile, MasterKey, DeveloperKey, PGPSignature +from .models import UserProfile, StaffGroup, MasterKey, DeveloperKey, PGPSignature class UserProfileInline(admin.StackedInline): @@ -15,6 +15,11 @@ class UserProfileAdmin(UserAdmin): list_filter = ('is_staff', 'is_superuser', 'is_active') +class StaffGroupAdmin(admin.ModelAdmin): + list_display = ('name', 'group', 'sort_order', 'member_title', 'slug') + prepopulated_fields = {'slug': ('name',)} + + class MasterKeyAdmin(admin.ModelAdmin): list_display = ('pgp_key', 'owner', 'created', 'revoker', 'revoked') search_fields = ('pgp_key', 'owner__username', 'revoker__username') @@ -36,6 +41,7 @@ class PGPSignatureAdmin(admin.ModelAdmin): admin.site.unregister(User) admin.site.register(User, UserProfileAdmin) +admin.site.register(StaffGroup, StaffGroupAdmin) admin.site.register(MasterKey, MasterKeyAdmin) admin.site.register(DeveloperKey, DeveloperKeyAdmin) diff --git a/devel/migrations/0002_staffgroup.py b/devel/migrations/0002_staffgroup.py new file mode 100644 index 00000000..5679e6a3 --- /dev/null +++ b/devel/migrations/0002_staffgroup.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0001_initial'), + ('devel', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='StaffGroup', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('name', models.CharField(max_length=100)), + ('slug', models.SlugField(unique=True, max_length=100)), + ('sort_order', models.PositiveIntegerField()), + ('member_title', models.CharField(max_length=100)), + ('description', models.TextField(blank=True)), + ('group', models.OneToOneField(to='auth.Group')), + ], + options={ + 'ordering': ('sort_order',), + }, + bases=(models.Model,), + ), + ] diff --git a/devel/models.py b/devel/models.py index 5c4d4fe7..b05800a5 100644 --- a/devel/models.py +++ b/devel/models.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- import pytz +from django.core.urlresolvers import reverse from django.db import models from django.db.models.signals import pre_save -from django.contrib.auth.models import User +from django.contrib.auth.models import User, Group from django_countries.fields import CountryField from .fields import PGPKeyField @@ -54,17 +55,29 @@ class UserProfile(models.Model): verbose_name_plural = 'additional profile data' def get_absolute_url(self): - # TODO: this is disgusting. find a way to consolidate this logic with - # public.views.userlist among other places, and make some constants or - # something so we aren't using copies of string names everywhere. - group_names = self.user.groups.values_list('name', flat=True) - if "Developers" in group_names: - prefix = "developers" - elif "Trusted Users" in group_names: - prefix = "trustedusers" - else: - prefix = "fellows" - return '/%s/#%s' % (prefix, self.user.username) + user = self.user + group = StaffGroup.objects.filter(group=user.groups.all()).first() + if group: + return '%s#%s' % (group.get_absolute_url(), user.username) + return None + + +class StaffGroup(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(max_length=100, unique=True) + group = models.OneToOneField(Group) + sort_order = models.PositiveIntegerField() + member_title = models.CharField(max_length=100) + description = models.TextField(blank=True) + + class Meta: + ordering = ('sort_order',) + + def __unicode__(self): + return self.name + + def get_absolute_url(self): + return reverse('people', args=[self.slug]) class MasterKey(models.Model): diff --git a/main/templatetags/flags.py b/main/templatetags/flags.py index 22f524ca..5b356561 100644 --- a/main/templatetags/flags.py +++ b/main/templatetags/flags.py @@ -8,6 +8,6 @@ def country_flag(country): if not country: return '' return '<span class="fam-flag fam-flag-%s" title="%s"></span> ' % ( - country.code.lower(), country.name) + unicode(country.code).lower(), unicode(country.name)) # vim: set ts=4 sw=4 et: diff --git a/mirrors/admin.py b/mirrors/admin.py index d5c89c2a..16a97ea2 100644 --- a/mirrors/admin.py +++ b/mirrors/admin.py @@ -11,7 +11,7 @@ from .models import (Mirror, MirrorProtocol, MirrorUrl, MirrorRsync, class MirrorUrlForm(forms.ModelForm): class Meta: model = MirrorUrl - fields = ('url', 'country', 'active') + fields = ('url', 'country', 'bandwidth', 'active') def clean_url(self): # is this a valid-looking URL? diff --git a/mirrors/migrations/0002_mirrorurl_bandwidth.py b/mirrors/migrations/0002_mirrorurl_bandwidth.py new file mode 100644 index 00000000..f0118199 --- /dev/null +++ b/mirrors/migrations/0002_mirrorurl_bandwidth.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mirrors', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='mirrorurl', + name='bandwidth', + field=models.FloatField(null=True, verbose_name=b'bandwidth (mbits)', blank=True), + preserve_default=True, + ), + ] diff --git a/mirrors/models.py b/mirrors/models.py index 641a6b97..820f3328 100644 --- a/mirrors/models.py +++ b/mirrors/models.py @@ -72,8 +72,9 @@ class MirrorUrl(models.Model): editable=False) has_ipv6 = models.BooleanField("IPv6 capable", default=False, editable=False) - created = models.DateTimeField(editable=False) active = models.BooleanField(default=True) + bandwidth = models.FloatField("bandwidth (mbits)", null=True, blank=True) + created = models.DateTimeField(editable=False) class Meta: verbose_name = 'mirror URL' diff --git a/mirrors/views.py b/mirrors/views.py index cffafbf5..65fa0123 100644 --- a/mirrors/views.py +++ b/mirrors/views.py @@ -4,7 +4,7 @@ import json from operator import attrgetter, itemgetter from django import forms -from django.forms.widgets import CheckboxSelectMultiple +from django.forms.widgets import SelectMultiple, CheckboxSelectMultiple from django.core.serializers.json import DjangoJSONEncoder from django.db import connection from django.db.models import Q @@ -14,7 +14,8 @@ from django.utils.timezone import now from django.views.decorators.cache import cache_page from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import condition -from django_countries.data import COUNTRIES +from django_countries import countries +from django_countries.fields import Country from .models import (Mirror, MirrorUrl, MirrorProtocol, MirrorLog, CheckLocation) @@ -22,7 +23,8 @@ from .utils import get_mirror_statuses, get_mirror_errors, DEFAULT_CUTOFF class MirrorlistForm(forms.Form): - country = forms.MultipleChoiceField(required=False) + country = forms.MultipleChoiceField(required=False, + widget=SelectMultiple(attrs={'size': '12'})) protocol = forms.MultipleChoiceField(required=False, widget=CheckboxSelectMultiple) ip_version = forms.MultipleChoiceField(required=False, @@ -30,8 +32,6 @@ class MirrorlistForm(forms.Form): widget=CheckboxSelectMultiple) use_mirror_status = forms.BooleanField(required=False) - countries = dict(COUNTRIES) - def __init__(self, *args, **kwargs): super(MirrorlistForm, self).__init__(*args, **kwargs) fields = self.fields @@ -49,8 +49,8 @@ class MirrorlistForm(forms.Form): country_codes.update(MirrorUrl.objects.filter(active=True, mirror__active=True).exclude(country='').values_list( 'country', flat=True).order_by().distinct()) - countries = [(code, self.countries[code]) for code in country_codes] - return sorted(countries, key=itemgetter(1)) + code_list = [(code, countries.name(code)) for code in country_codes] + return sorted(code_list, key=itemgetter(1)) def as_div(self): "Returns this form rendered as HTML <divs>s." @@ -142,14 +142,29 @@ def mirrors(request): mirror_list = Mirror.objects.select_related().order_by('tier', 'name') protos = MirrorUrl.objects.values_list( 'mirror_id', 'protocol__protocol').order_by( - 'mirror__id', 'protocol__protocol').distinct() + 'mirror_id', 'protocol__protocol').distinct() + countries = MirrorUrl.objects.values_list( + 'mirror_id', 'country').order_by( + 'mirror_id', 'country').distinct() + if not request.user.is_authenticated(): mirror_list = mirror_list.filter(public=True, active=True) - protos = protos.filter(mirror__public=True, mirror__active=True) + protos = protos.filter( + mirror__public=True, mirror__active=True, active=True) + countries = countries.filter( + mirror__public=True, mirror__active=True, active=True) + protos = {k: list(v) for k, v in groupby(protos, key=itemgetter(0))} + countries = {k: list(v) for k, v in groupby(countries, key=itemgetter(0))} + for mirror in mirror_list: - items = protos.get(mirror.id, []) - mirror.protocols = [item[1] for item in items] + item_protos = protos.get(mirror.id, []) + mirror.protocols = [item[1] for item in item_protos] + mirror.country = None + item_countries = countries.get(mirror.id, []) + if len(item_countries) == 1: + mirror.country = Country(item_countries[0][1]) + return render(request, 'mirrors/mirrors.html', {'mirror_list': mirror_list}) diff --git a/public/views.py b/public/views.py index 57634983..1b79e7c8 100644 --- a/public/views.py +++ b/public/views.py @@ -5,11 +5,11 @@ from operator import attrgetter from django.conf import settings from django.contrib.auth.models import User from django.db.models import Count, Q -from django.http import Http404, HttpResponse -from django.shortcuts import render +from django.http import HttpResponse +from django.shortcuts import get_object_or_404, render from django.views.decorators.cache import cache_control, cache_page -from devel.models import MasterKey, PGPSignature +from devel.models import MasterKey, PGPSignature, StaffGroup from main.models import Arch, Repo, Donor from mirrors.models import MirrorUrl from news.models import News @@ -28,38 +28,18 @@ def index(request): context = { 'news_updates': News.objects.order_by('-postdate', '-id')[:15], 'pkg_updates': updates, + 'staff_groups': StaffGroup.objects.all(), } return render(request, 'public/index.html', context) -USER_LISTS = { - 'hackers': { - 'user_type': 'Hackers', - 'user_title': 'Hacker', - 'description': "This is a list of the current "+settings.BRANDING_SHORTNAME+" Hackers. They maintain the [libre] package repository and keep the [core], [extra] and [community] repositories clean of unfree software, in addition to doing any other developer duties.", - }, - 'fellows': { - 'user_type': 'Fellows', - 'user_title': 'Fellow', - 'description': "Below you can find a list of ex-hackers (aka project fellows). These folks helped make "+settings.BRANDING_SHORTNAME+" what it is today. Thanks!", - }, -} - @cache_control(max_age=307) -def userlist(request, user_type='hackers'): - users = User.objects.order_by( - 'username').select_related('userprofile') - if user_type == 'hackers': - users = users.filter(is_active=True, groups__name="Hackers") - elif user_type == 'fellows': - users = users.filter(is_active=False, - groups__name__in=["Hackers"]) - else: - raise Http404 +def people(request, slug): + group = get_object_or_404(StaffGroup, slug=slug) + users = User.objects.filter(groups=group.group).order_by( + 'first_name', 'last_name').select_related('userprofile') - users = users.distinct() - context = USER_LISTS[user_type].copy() - context['users'] = users + context = {'group': group, 'users': users} return render(request, 'public/userlist.html', context) diff --git a/settings.py b/settings.py index 5ee17af3..fa27b2f2 100644 --- a/settings.py +++ b/settings.py @@ -199,6 +199,11 @@ BRANDING_WIKINAME = 'ParabolaWiki' BRANDING_EMAIL = 'Parabola Website Notification <nobody@parabola.nu>' BRANDING_OSEARCH_TAGS = 'gnu linuxlibre parabola package software' +# Country name overrides for display purposes +COUNTRIES_OVERRIDE = { + 'MK': 'Macedonia', +} + ## Import local settings from local_settings import * diff --git a/sitemaps.py b/sitemaps.py index d79b00b5..eb4e05d9 100644 --- a/sitemaps.py +++ b/sitemaps.py @@ -127,9 +127,6 @@ class BaseSitemap(Sitemap): 'page-about', 'page-art', 'page-svn', - 'page-devs', - 'page-tus', - 'page-fellows', 'page-donate', 'feeds-list', 'mirror-list', diff --git a/templates/mirrors/mirrors.html b/templates/mirrors/mirrors.html index 13701e5a..3450d439 100644 --- a/templates/mirrors/mirrors.html +++ b/templates/mirrors/mirrors.html @@ -1,8 +1,12 @@ {% extends "base.html" %} {% load cycle from future %} {% load static from staticfiles %} +{% load flags %} + {% block title %}{{ BRANDING_DISTRONAME }} - Mirror Overview{% endblock %} +{% block head %}<link rel="stylesheet" type="text/css" href="{% static "flags/fam.css" %}" media="screen, projection" />{% endblock %} + {% block content %} <div id="dev-mirrorlist" class="box"> <h2>Mirror Overview</h2> @@ -10,6 +14,7 @@ <thead> <tr> <th>Server</th> + <th>Country</th> <th>Tier</th> <th>ISOs</th> <th>Protocols</th> @@ -26,6 +31,7 @@ <tr class="{% cycle 'odd' 'even' %}"> <td><a href="{{ mirror.get_absolute_url }}" title="Mirror details for {{ mirror.name }}">{{ mirror.name }}</a></td> + <td class="country">{% if mirror.country %}{% country_flag mirror.country %}{{ mirror.country.name }}{% else %}Various{% endif %}</td> <td>{{ mirror.get_tier_display }}</td> <td>{{ mirror.isos|yesno|capfirst }}</td> <td class="wrap">{{ mirror.protocols|join:", " }}</td> @@ -44,7 +50,7 @@ <script type="text/javascript" src="{% static "archweb.js" %}"></script> <script type="text/javascript"> $(document).ready(function() { - $(".results").tablesorter({widgets: ['zebra'], sortList: [[1,0], [0,0]]}); + $(".results").tablesorter({widgets: ['zebra'], sortList: [[2,0], [0,0]]}); }); </script> {% endblock %} diff --git a/templates/public/developer_list.html b/templates/public/developer_list.html index 15a6c8bb..041780d7 100644 --- a/templates/public/developer_list.html +++ b/templates/public/developer_list.html @@ -21,7 +21,7 @@ <meta itemprop="name" content="{{ dev.get_full_name|escape }}"/> <meta itemprop="givenName" content="{{ dev.first_name|escape }}"/> <meta itemprop="familyName" content="{{ dev.last_name|escape }}"/> - <meta itemprop="jobTitle" content="{{ user_title|escape }}"/> + <meta itemprop="jobTitle" content="{{ group.member_title|escape }}"/> <div style="display:none" itemprop="memberOf" itemscope itemtype="http://schema.org/Organization"> <meta itemprop="name" content="{{ BRANDING_DISTRONAME }}"/> </div> @@ -53,7 +53,7 @@ <th>Occupation:</th> <td>{{ prof.occupation }}</td> </tr><tr> - <th>YOB:</th> + <th>Birth Year:</th> <td itemprop="birthDate">{% if prof.yob %}{{ prof.yob }}{% endif %}</td> </tr><tr> <th>Location:</th> diff --git a/templates/public/index.html b/templates/public/index.html index e7174b45..f30b00f8 100644 --- a/templates/public/index.html +++ b/templates/public/index.html @@ -171,8 +171,9 @@ <h4>People</h4> <ul> - <li><a href="{% url 'page-devs' %}" title="Active hackers">Hackers</a></li> - <li><a href="{% url 'page-fellows' %}" title="Retired hackers">Fellows</a></li> + {% for group in staff_groups %} + <li><a href="{% url 'people' group.slug %}" title="More info about {{ group.name }}">{{ group.name }}</a></li> + {% endfor %} <li><a href="{% url 'page-keys' %}" title="Package/Database signing master keys">Signing Master Keys</a></li> </ul> diff --git a/templates/public/userlist.html b/templates/public/userlist.html index 6292af83..d49a1539 100644 --- a/templates/public/userlist.html +++ b/templates/public/userlist.html @@ -2,16 +2,16 @@ {% load static from staticfiles %} {% load cache %} -{% block title %}{{ BRANDING_DISTRONAME }} - {{ user_type }}{% endblock %} +{% block title %}{{ BRANDING_DISTRONAME }} - {{ group.name }}{% endblock %} {% block head %}<link rel="stylesheet" type="text/css" href="{% static "flags/fam.css" %}" media="screen, projection" />{% endblock %} {% block content %} -{% cache 600 dev-tu-profiles user_type %} +{% cache 600 dev-tu-profiles group.name %} <div id="dev-tu-profiles" class="box"> - <h2>{{BRANDING_DISTRONAME}} {{user_type}}</h2> + <h2>{{BRANDING_DISTRONAME}} {{ group.name }}</h2> - <p>{{description}}</p> + <p>{{ group.description }}</p> {% with users as dev_list %} {% include 'public/developer_list.html' %} @@ -29,14 +29,13 @@ urlpatterns += patterns('public.views', {}, 'page-art'), (r'^https/$', TemplateView.as_view(template_name='public/https.html'), {}, 'page-https'), - (r'^hackers/$', 'userlist', { 'user_type':'hackers' }, 'page-devs'), - (r'^fellows/$', 'userlist', { 'user_type':'fellows' }, 'page-fellows'), (r'^donate/$', RedirectView.as_view('https://wiki.parabola.nu/Donations'), {}, 'page-donate'), (r'^download/$', RedirectView.as_view('https://wiki.parabola.nu/Get_Parabola'), {}, 'page-download'), (r'^master-keys/$', 'keys', {}, 'page-keys'), (r'^master-keys/json/$', 'keys_json', {}, 'pgp-keys-json'), + (r'^people/(?P<slug>[-\w]+)/$', 'people', {}, 'people'), ) # Feeds patterns, used below @@ -94,15 +93,18 @@ urlpatterns += patterns('django.contrib.auth.views', legacy_urls = ( ('^about.php', '/about/'), ('^changelog.php', '/packages/?sort=-last_update'), - ('^devs.php', '/developers/'), + ('^devs.php', '/people/developers/'), ('^donations.php', '/donate/'), ('^download.php', '/download/'), ('^index.php', '/'), ('^logos.php', '/art/'), ('^news.php', '/news/'), ('^packages.php', '/packages/'), - ('^people.php', '/developers/'), + ('^people.php', '/people/developers/'), ('^todolists/$', '/todo/'), + ('^developers/$', '/people/developers/'), + ('^fellows/$', '/people/developer-fellows/'), + ('^trustedusers/$', '/people/trusted-users/'), ('^docs/en/guide/install/arch-install-guide.html', 'https://wiki.parabola.nu/Installation_Guide'), |