From 18e86f50bfa33997cf54733c7d24840cdec4e7aa Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 6 Jan 2011 10:25:00 -0600 Subject: Update readme Signed-off-by: Dan McGee --- README | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/README b/README index dc43e9da..6b492d84 100644 --- a/README +++ b/README @@ -33,37 +33,41 @@ packages, you will probably want the following: 1. Run `virtualenv`. - $ cd /path/to/archweb && virtualenv ../archweb + $ cd /path/to/archweb && virtualenv ../archweb-env + +2. Source the virtualenv. + + $ . ../archweb-env/bin/activate 2. Install dependencies through `pip`. - $ pip install -r requirements.txt + (archweb-env) $ pip install -r requirements.txt 3. Copy `local_settings.py.example` to `local_settings.py` and modify. Make sure to uncomment the appropriate db section (either sqlite or mysql). 4. Sync the database to create it. - $ ./manage.py syncdb + (archweb-env) $ ./manage.py syncdb 5. Migrate changes. - $ ./manage.py migrate + (archweb-env) $ ./manage.py migrate 6. Load the fixtures to prepopulate some data. - $ ./manage.py loaddata main/fixtures/arches.json - # ./manage.py loaddata main/fixtures/repos.json - # ./manage.py loaddata mirrors/fixtures/mirrorprotocols.json + (archweb-env) $ ./manage.py loaddata main/fixtures/arches.json + (archweb-env) $ ./manage.py loaddata main/fixtures/repos.json + (archweb-env) $ ./manage.py loaddata mirrors/fixtures/mirrorprotocols.json 7. Use the following commands to start a service instance - $ ./manage.py runserver + (archweb-env) $ ./manage.py runserver 8. To optionally populate the database with real data: - $ wget ftp://ftp.archlinux.org/core/os/i686/core.db.tar.gz - $ ./manage.py reporead i686 core.db.tar.gz + (archweb-env) $ wget ftp://ftp.archlinux.org/core/os/i686/core.db.tar.gz + (archweb-env) $ ./manage.py reporead i686 core.db.tar.gz Alter architecture and repo to get x86\_64 and packages from other repos if needed. -- cgit v1.2.3-2-g168b From d8b1f9982466a4a4e8c224f335767084a5c6a301 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 6 Jan 2011 10:28:06 -0600 Subject: Remove default admins Set them in local_settings instead. Signed-off-by: Dan McGee --- settings.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/settings.py b/settings.py index f98f709c..6b6e0cc6 100644 --- a/settings.py +++ b/settings.py @@ -6,9 +6,7 @@ DEBUG = False TEMPLATE_DEBUG = DEBUG ## Notification admins -ADMINS = ( - ('Dan McGee', 'dan@archlinux.org'), -) +ADMINS = () # Set managers to admins MANAGERS = ADMINS -- cgit v1.2.3-2-g168b From 8d7941c1ddc40623d7050bb0809453603f6ccad9 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Thu, 6 Jan 2011 10:30:46 -0600 Subject: Settings file tweaks Signed-off-by: Dan McGee --- settings.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/settings.py b/settings.py index 6b6e0cc6..8e916e36 100644 --- a/settings.py +++ b/settings.py @@ -29,14 +29,6 @@ DEFAULT_CHARSET = 'utf-8' SITE_ID = 1 -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = False - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = False - # Default date format in templates for 'date' filter DATE_FORMAT = 'Y-m-d' @@ -45,10 +37,13 @@ DATE_FORMAT = 'Y-m-d' # Examples: "http://foo.com/media/", "/media/". ADMIN_MEDIA_PREFIX = '/media/admin_media/' -# login url +# Login URL configuration LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/' +# Set django's User stuff to use our profile model +AUTH_PROFILE_MODULE = 'main.UserProfile' + # List of callables that know how to import templates from various sources. TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', @@ -94,12 +89,8 @@ TEMPLATE_LOADERS = ( 'django.template.loaders.app_directories.Loader', ) -# Set django's User stuff to use our profile model -# format is app.model -AUTH_PROFILE_MODULE = 'main.UserProfile' - +# Configure where sessions and messages should reside MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' - SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' INSTALLED_APPS = ( -- cgit v1.2.3-2-g168b From bf3893768c42e7c0d4f4205819ef4e5ada1b2707 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 11:05:10 -0600 Subject: Add pytz as a project requirement Signed-off-by: Dan McGee --- requirements.txt | 1 + requirements_prod.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index f4d80eeb..ba21a59a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ Django==1.2.4 Markdown==2.0.3 South==0.7.3 +pytz>=2010o diff --git a/requirements_prod.txt b/requirements_prod.txt index 49ca44c4..b8665f35 100644 --- a/requirements_prod.txt +++ b/requirements_prod.txt @@ -3,3 +3,4 @@ Markdown==2.0.3 MySQL-python==1.2.3c1 South==0.7.3 python-memcached==1.47 +pytz>=2010o -- cgit v1.2.3-2-g168b From 9a1971e24fe15ccdb74f3a8a59d735504f2797be Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 11:41:59 -0600 Subject: Add time zone field to developer profile This will be used by the developer world clock page soon to come. Default everyone to "UTC" for now. Signed-off-by: Dan McGee --- .../0037_auto__add_field_userprofile_time_zone.py | 154 +++++++++++++++++++++ main/models.py | 9 +- 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 main/migrations/0037_auto__add_field_userprofile_time_zone.py diff --git a/main/migrations/0037_auto__add_field_userprofile_time_zone.py b/main/migrations/0037_auto__add_field_userprofile_time_zone.py new file mode 100644 index 00000000..9b9b8beb --- /dev/null +++ b/main/migrations/0037_auto__add_field_userprofile_time_zone.py @@ -0,0 +1,154 @@ +# 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 'UserProfile.time_zone' + db.add_column('user_profiles', 'time_zone', self.gf('django.db.models.fields.CharField')(default='UTC', max_length=100), keep_default=False) + + def backwards(self, orm): + # Deleting field 'UserProfile.time_zone' + db.delete_column('user_profiles', 'time_zone') + + 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'}) + }, + 'main.arch': { + 'Meta': {'ordering': "['name']", 'object_name': 'Arch', 'db_table': "'arches'"}, + 'agnostic': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + 'main.donor': { + 'Meta': {'ordering': "['name']", 'object_name': 'Donor', 'db_table': "'donors'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'visible': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + }, + 'main.package': { + 'Meta': {'ordering': "('pkgname',)", 'object_name': 'Package', 'db_table': "'packages'"}, + 'arch': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Arch']"}), + 'build_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'compressed_size': ('django.db.models.fields.BigIntegerField', [], {'null': 'True'}), + 'filename': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'files_last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'flag_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'installed_size': ('django.db.models.fields.BigIntegerField', [], {'null': 'True'}), + 'last_update': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'license': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'packager': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'packager_str': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgbase': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'pkgdesc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'pkgname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'repo': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'packages'", 'to': "orm['main.Repo']"}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}) + }, + 'main.packagedepend': { + 'Meta': {'object_name': 'PackageDepend', 'db_table': "'package_depends'"}, + 'depname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'depvcmp': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.packagefile': { + 'Meta': {'object_name': 'PackageFile', 'db_table': "'package_files'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.repo': { + 'Meta': {'ordering': "['name']", 'object_name': 'Repo', 'db_table': "'repos'"}, + 'bugs_project': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'svn_root': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'testing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'main.signoff': { + 'Meta': {'object_name': 'Signoff'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'packager': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}), + 'pkgrel': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'pkgver': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.todolist': { + 'Meta': {'object_name': 'Todolist', 'db_table': "'todolists'"}, + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'date_added': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.todolistpkg': { + 'Meta': {'unique_together': "(('list', 'pkg'),)", 'object_name': 'TodolistPkg', 'db_table': "'todolist_pkgs'"}, + 'complete': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'list': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Todolist']"}), + 'pkg': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Package']"}) + }, + 'main.userprofile': { + 'Meta': {'object_name': 'UserProfile', 'db_table': "'user_profiles'"}, + 'alias': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'allowed_repos': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Repo']", 'symmetrical': 'False', 'blank': 'True'}), + 'favorite_distros': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'interests': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'languages': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'notify': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'occupation': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'other_contact': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'picture': ('django.db.models.fields.files.FileField', [], {'default': "'devs/silhouette.png'", 'max_length': '100'}), + 'public_email': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'roles': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'time_zone': ('django.db.models.fields.CharField', [], {'default': "'UTC'", 'max_length': '100'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': "orm['auth.User']"}), + 'website': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'yob': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['main'] diff --git a/main/models.py b/main/models.py index 8858b17b..0e9e55a1 100644 --- a/main/models.py +++ b/main/models.py @@ -2,18 +2,23 @@ from django.db import models from django.contrib.auth.models import User from django.contrib.sites.models import Site -from main.utils import cache_function +from main.utils import cache_function, make_choice from packages.models import PackageRelation from itertools import groupby +import pytz from operator import attrgetter class UserProfile(models.Model): - id = models.AutoField(primary_key=True) # not technically needed notify = models.BooleanField( "Send notifications", default=True, help_text="When enabled, send user 'flag out-of-date' notifications") + time_zone = models.CharField( + max_length=100, + choices=make_choice(pytz.all_timezones), + default="UTC", + help_text="Used for developer clock page") alias = models.CharField( max_length=50, help_text="Required field") -- cgit v1.2.3-2-g168b From c04d4abc88cdf0891bff2b1ce6d1d746c5b9b3c9 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 11:47:11 -0600 Subject: Add developer world clocks page This should make it easier for everyone to figure out whether someone is awake, sleeping, and all that fun stuff. It does require everyone to update their profile and fill in the field, but that shouldn't be too hard of a task. Don't suggest jokes to me Saturday morning on IRC unless you really want to see them implemented. Thanks, Pierre! Signed-off-by: Dan McGee --- devel/urls.py | 1 + devel/views.py | 25 ++++++++++++++++++++++- templates/devel/clock.html | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 templates/devel/clock.html diff --git a/devel/urls.py b/devel/urls.py index 23dd2d9f..0a050a92 100644 --- a/devel/urls.py +++ b/devel/urls.py @@ -2,6 +2,7 @@ from django.conf.urls.defaults import patterns urlpatterns = patterns('devel.views', (r'^$', 'index'), + (r'^clock/$', 'clock'), (r'^notify/$', 'change_notify'), (r'^profile/$', 'change_profile'), (r'^newuser/$', 'new_user_form'), diff --git a/devel/views.py b/devel/views.py index 710bfff5..b26c7af0 100644 --- a/devel/views.py +++ b/devel/views.py @@ -13,6 +13,8 @@ from main.models import UserProfile from packages.models import PackageRelation from .utils import get_annotated_maintainers +import datetime +import pytz import random from string import ascii_letters, digits @@ -38,10 +40,31 @@ def index(request): 'maintainers': maintainers, 'flagged' : flagged, 'todopkgs' : todopkgs, - } + } return direct_to_template(request, 'devel/index.html', page_dict) +@login_required +@never_cache +def clock(request): + devs = User.objects.filter(is_active=True).order_by( + 'username').select_related('userprofile') + + # now annotate each dev object with their current time + now = datetime.datetime.now() + utc_now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) + for dev in devs: + tz = pytz.timezone(dev.userprofile.time_zone) + dev.current_time = utc_now.astimezone(tz) + + page_dict = { + 'developers': devs, + 'now': now, + 'utc_now': utc_now, + } + + return direct_to_template(request, 'devel/clock.html', page_dict) + @login_required def change_notify(request): maint = User.objects.get(username=request.user.username) diff --git a/templates/devel/clock.html b/templates/devel/clock.html new file mode 100644 index 00000000..ec567c2d --- /dev/null +++ b/templates/devel/clock.html @@ -0,0 +1,49 @@ +{% extends "base.html" %} + +{% block title %}Arch Linux - Developer World Clocks{% endblock %} + +{% block content %} +
+

Developer World Clocks

+ +

This page helps prevent you from waking a sleeping developer. It also + depends on developers keeping the time zone information up to date, so if + you see 'UTC' listed, pester them to update their settings.

+

+ Arch Server Time: {{ now|date:"Y-m-d H:i" }}
+ UTC Time: {{ utc_now|date:"Y-m-d H:i" }} +

+ + + + + + + + + + + + + {% for dev in developers %} + + + + + + + + {% endfor %} + +
DeveloperUsernameLocationTime ZoneCurrent Time
{{ dev.get_full_name }}{{ dev.username }}{{ dev.userprofile.location }}{{ dev.userprofile.time_zone }}{{ dev.current_time|date:"Y-m-d H:i" }}
+
+{% load cdn %}{% jquery %} + + + +{% endblock %} -- cgit v1.2.3-2-g168b From c18cd21e536592b6ed482126ee423f38b9ac9257 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Tue, 21 Dec 2010 19:02:22 -0600 Subject: Remove automatic ID column definitions Signed-off-by: Dan McGee --- main/models.py | 9 --------- news/models.py | 1 - 2 files changed, 10 deletions(-) diff --git a/main/models.py b/main/models.py index 8858b17b..61282153 100644 --- a/main/models.py +++ b/main/models.py @@ -9,7 +9,6 @@ from itertools import groupby from operator import attrgetter class UserProfile(models.Model): - id = models.AutoField(primary_key=True) # not technically needed notify = models.BooleanField( "Send notifications", default=True, @@ -49,7 +48,6 @@ class PackageManager(models.Manager): class Donor(models.Model): - id = models.AutoField(primary_key=True) name = models.CharField(max_length=255, unique=True) visible = models.BooleanField(default=True, help_text="Should we show this donor on the public page?") @@ -62,7 +60,6 @@ class Donor(models.Model): ordering = ['name'] class Arch(models.Model): - id = models.AutoField(primary_key=True) name = models.CharField(max_length=255, unique=True) agnostic = models.BooleanField(default=False, help_text="Is this architecture non-platform specific?") @@ -79,7 +76,6 @@ class Arch(models.Model): verbose_name_plural = 'arches' class Repo(models.Model): - id = models.AutoField(primary_key=True) name = models.CharField(max_length=255, unique=True) testing = models.BooleanField(default=False, help_text="Is this repo meant for package testing?") @@ -100,7 +96,6 @@ class Repo(models.Model): verbose_name_plural = 'repos' class Package(models.Model): - id = models.AutoField(primary_key=True) repo = models.ForeignKey(Repo, related_name="packages") arch = models.ForeignKey(Arch, related_name="packages") pkgname = models.CharField(max_length=255, db_index=True) @@ -308,14 +303,12 @@ class Signoff(models.Model): packager = models.ForeignKey(User) class PackageFile(models.Model): - id = models.AutoField(primary_key=True) pkg = models.ForeignKey('Package') path = models.CharField(max_length=255) class Meta: db_table = 'package_files' class PackageDepend(models.Model): - id = models.AutoField(primary_key=True) pkg = models.ForeignKey('Package') depname = models.CharField(db_index=True, max_length=255) depvcmp = models.CharField(max_length=255) @@ -323,7 +316,6 @@ class PackageDepend(models.Model): db_table = 'package_depends' class Todolist(models.Model): - id = models.AutoField(primary_key=True) creator = models.ForeignKey(User) name = models.CharField(max_length=255) description = models.TextField() @@ -351,7 +343,6 @@ class Todolist(models.Model): return '/todo/%i/' % self.id class TodolistPkg(models.Model): - id = models.AutoField(primary_key=True) list = models.ForeignKey('Todolist') pkg = models.ForeignKey('Package') complete = models.BooleanField(default=False) diff --git a/news/models.py b/news/models.py index e2486c96..c2d644b7 100644 --- a/news/models.py +++ b/news/models.py @@ -2,7 +2,6 @@ from django.db import models from django.contrib.auth.models import User class News(models.Model): - id = models.AutoField(primary_key=True) slug = models.SlugField(max_length=255, unique=True) author = models.ForeignKey(User, related_name='news_author') postdate = models.DateTimeField("post date", auto_now_add=True, db_index=True) -- cgit v1.2.3-2-g168b From 139181399e43fc25b99482cfb8acd80934e1ed52 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 12:14:37 -0600 Subject: Link to dev clocks page Signed-off-by: Dan McGee --- templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/base.html b/templates/base.html index c7b26a9e..03795dd9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -39,7 +39,7 @@
  • News
  • Signoffs
  • Todos
  • -
  • Arch Differences
  • +
  • Dev Clocks
  • Archives
  • Mirrors
  • -- cgit v1.2.3-2-g168b From ef016929a9863810cb0e9078c13bd1142922a63d Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 12:31:22 -0600 Subject: Add time zone format spec to clock page Signed-off-by: Dan McGee --- templates/devel/clock.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/devel/clock.html b/templates/devel/clock.html index ec567c2d..1bc9a849 100644 --- a/templates/devel/clock.html +++ b/templates/devel/clock.html @@ -10,8 +10,8 @@ depends on developers keeping the time zone information up to date, so if you see 'UTC' listed, pester them to update their settings.

    - Arch Server Time: {{ now|date:"Y-m-d H:i" }}
    - UTC Time: {{ utc_now|date:"Y-m-d H:i" }} + Arch Server Time: {{ now|date:"Y-m-d H:i T" }}
    + UTC Time: {{ utc_now|date:"Y-m-d H:i T" }}

    @@ -31,7 +31,7 @@ - + {% endfor %} -- cgit v1.2.3-2-g168b From ec5649fada6d91ea7d1a75efe7e42699d0f0f7b6 Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 17:38:26 -0600 Subject: Use common timezones only No need to show historical and deprecated zone names. Signed-off-by: Dan McGee --- main/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/models.py b/main/models.py index 7ce2d2f4..ff2ecf02 100644 --- a/main/models.py +++ b/main/models.py @@ -16,7 +16,7 @@ class UserProfile(models.Model): help_text="When enabled, send user 'flag out-of-date' notifications") time_zone = models.CharField( max_length=100, - choices=make_choice(pytz.all_timezones), + choices=make_choice(pytz.common_timezones), default="UTC", help_text="Used for developer clock page") alias = models.CharField( -- cgit v1.2.3-2-g168b From 09bccb50e7c1bcbe15ca4f0e26c2f82cd816accb Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sat, 8 Jan 2011 18:40:47 -0600 Subject: Only match full text on built-in short date parser Signed-off-by: Dan McGee --- media/jquery.tablesorter.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/jquery.tablesorter.min.js b/media/jquery.tablesorter.min.js index 64c70071..7d54b3bc 100644 --- a/media/jquery.tablesorter.min.js +++ b/media/jquery.tablesorter.min.js @@ -1,2 +1,2 @@ -(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;ib)?1:0));};function sortTextDesc(a,b){return((ba)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;ib)?1:0));};function sortTextDesc(a,b){return((ba)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i Date: Sat, 8 Jan 2011 18:41:23 -0600 Subject: Add a long datetime parser to table sorting code This comes into play on our new developer clocks page, where the last column was not sorting at all as expected. Signed-off-by: Dan McGee --- media/archweb.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/media/archweb.js b/media/archweb.js index c5025ded..1c80ab64 100644 --- a/media/archweb.js +++ b/media/archweb.js @@ -36,18 +36,34 @@ if(typeof $.tablesorter !== "undefined") { $.tablesorter.addParser({ /* sorts duration; put '', 'unknown', and '∞' last. */ id: 'duration', - is: function(s,table) { + re: /^([0-9]+):([0-5][0-9])$/, + is: function(s) { var special = ['', 'unknown', '∞']; - return ($.inArray(s, special) > -1) || /^[0-9]+:[0-5][0-9]$/.test(s); + return ($.inArray(s, special) > -1) || this.re.test(s); }, format: function(s) { var special = ['', 'unknown', '∞']; if($.inArray(s, special) > -1) return Number.MAX_VALUE; - matches = /^([0-9]+):([0-5][0-9])$/.exec(s); + var matches = this.re.exec(s); return matches[1] * 60 + matches[2]; }, type: 'numeric' }); + $.tablesorter.addParser({ + id: 'longDateTime', + re: /^(\d{4})-(\d{2})-(\d{2}) ([012]\d):([0-5]\d)(:([0-5]\d))?( (\w+))?$/, + is: function (s) { + return this.re.test(s); + }, + format: function (s) { + var matches = this.re.exec(s); + /* skip group 6, group 7 is optional seconds */ + if(matches[7] == undefined) matches[7] = "0"; + return $.tablesorter.formatFloat(new Date( + matches[1],matches[2],matches[3],matches[4],matches[5],matches[7]).getTime()); + }, + type: "numeric" + }); } /* news/add.html */ -- cgit v1.2.3-2-g168b
    {{ dev.username }} {{ dev.userprofile.location }} {{ dev.userprofile.time_zone }}{{ dev.current_time|date:"Y-m-d H:i" }}{{ dev.current_time|date:"Y-m-d H:i T" }}