From 4b29603d79cc1f79c66786684f27ec9abfbaa825 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 17 Oct 2011 01:34:04 +0200 Subject: [PATCH 01/21] Initial commit --- .gitignore | 5 ++ __init__.py | 0 blog/__init__.py | 0 blog/admin.py | 4 ++ blog/models.py | 33 ++++++++++ blog/tests.py | 23 +++++++ blog/urls.py | 9 +++ blog/views.py | 55 ++++++++++++++++ links/__init__.py | 0 links/admin.py | 4 ++ links/models.py | 35 ++++++++++ links/tests.py | 16 +++++ links/urls.py | 5 ++ links/views.py | 12 ++++ local_settings.py.example | 15 +++++ main/__init__.py | 0 main/admin.py | 4 ++ main/models.py | 24 +++++++ main/signals.py | 0 main/tests.py | 23 +++++++ main/urls.py | 4 ++ main/views.py | 13 ++++ manage.py | 11 ++++ projects/__init__.py | 0 projects/admin.py | 6 ++ projects/models.py | 59 +++++++++++++++++ projects/urls.py | 13 ++++ projects/views.py | 24 +++++++ settings.py | 91 ++++++++++++++++++++++++++ templates/admin/login.html | 50 ++++++++++++++ templates/base.html | 44 +++++++++++++ templates/blog/base.html | 5 ++ templates/blog/posts.html | 42 ++++++++++++ templates/blog/tags.html | 19 ++++++ templates/home.html | 88 +++++++++++++++++++++++++ templates/links/links.html | 20 ++++++ templates/projects/base.html | 3 + templates/projects/project_detail.html | 52 +++++++++++++++ templates/projects/project_list.html | 20 ++++++ urls.py | 19 ++++++ 40 files changed, 850 insertions(+) create mode 100644 .gitignore create mode 100644 __init__.py create mode 100644 blog/__init__.py create mode 100644 blog/admin.py create mode 100644 blog/models.py create mode 100644 blog/tests.py create mode 100644 blog/urls.py create mode 100644 blog/views.py create mode 100644 links/__init__.py create mode 100644 links/admin.py create mode 100644 links/models.py create mode 100644 links/tests.py create mode 100644 links/urls.py create mode 100644 links/views.py create mode 100644 local_settings.py.example create mode 100644 main/__init__.py create mode 100644 main/admin.py create mode 100644 main/models.py create mode 100644 main/signals.py create mode 100644 main/tests.py create mode 100644 main/urls.py create mode 100644 main/views.py create mode 100644 manage.py create mode 100644 projects/__init__.py create mode 100644 projects/admin.py create mode 100644 projects/models.py create mode 100644 projects/urls.py create mode 100644 projects/views.py create mode 100644 settings.py create mode 100644 templates/admin/login.html create mode 100644 templates/base.html create mode 100644 templates/blog/base.html create mode 100644 templates/blog/posts.html create mode 100644 templates/blog/tags.html create mode 100644 templates/home.html create mode 100644 templates/links/links.html create mode 100644 templates/projects/base.html create mode 100644 templates/projects/project_detail.html create mode 100644 templates/projects/project_list.html create mode 100644 urls.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db82c7d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.pyc +local_settings.py +static +.toudou +test.db diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/__init__.py b/blog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blog/admin.py b/blog/admin.py new file mode 100644 index 0000000..ca32d1f --- /dev/null +++ b/blog/admin.py @@ -0,0 +1,4 @@ +from blog.models import Post +from django.contrib import admin + +admin.site.register(Post) diff --git a/blog/models.py b/blog/models.py new file mode 100644 index 0000000..126ba57 --- /dev/null +++ b/blog/models.py @@ -0,0 +1,33 @@ +from django.db import models +from main.models import Tag, Activity +from django.db.models.signals import post_save, post_delete + +class Post(models.Model): + subject = models.CharField(max_length=500) + body = models.TextField() + tags = models.ManyToManyField(Tag, null=True, blank=True) + postdate = models.DateTimeField(auto_now=True) + + def __unicode__(self): + return self.subject + +def post_saved_callback(sender, **kwargs): + if kwargs['created']: + acttype = 'add' + else: + acttype = 'edit' + + a = Activity(actcategory='blog', + actdescription=kwargs["instance"].subject, + acttype = acttype, + objpk = kwargs["instance"].pk) + a.save() + +def post_deleted_callback(sender, **kwargs): + a = Activity(actcategory='blog', + actdescription=kwargs["instance"].subject, + acttype = 'delete') + a.save() + +post_save.connect(post_saved_callback, sender=Post) +post_delete.connect(post_deleted_callback, sender=Post) diff --git a/blog/tests.py b/blog/tests.py new file mode 100644 index 0000000..2247054 --- /dev/null +++ b/blog/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/blog/urls.py b/blog/urls.py new file mode 100644 index 0000000..c4137ed --- /dev/null +++ b/blog/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('blog.views', + (r'^$', 'index'), + (r'^(?P\d+)/$', 'index'), + (r'^post/(?P\d+)/$', 'post'), + (r'^tags/$', 'tags'), + (r'^tag/(?P[\w_]+)/$', 'tag'), +) diff --git a/blog/views.py b/blog/views.py new file mode 100644 index 0000000..06a4aba --- /dev/null +++ b/blog/views.py @@ -0,0 +1,55 @@ +# Create your views here. +from django.http import HttpResponse +from django.shortcuts import render_to_response +from django.template import Context, loader +from django.views.generic.simple import direct_to_template +from blog.models import Post, Tag + +def index(request, page=0): + item_count = 7 + + page = int(page) + start_num = (page * item_count) + end_num = start_num + item_count + + post_list = Post.objects.all().order_by("-postdate")[start_num:end_num] + + has_previous = page > 0 + has_next = end_num < Post.objects.all().count() + + c = { + 'postlist': post_list, + 'has_next': has_next, + 'has_previous': has_previous, + 'next_page': page + 1, + 'previous_page': page - 1 + } + + return direct_to_template(request, "blog/posts.html", c) + +def post(request, post_id): + post = Post.objects.filter(pk=post_id) + t = loader.get_template("blog/posts.html") + c = Context({ + 'postlist': post, + }) + + return HttpResponse(t.render(c)) + +def tags(request): + tag_list = Tag.objects.all() + t = loader.get_template("blog/tags.html") + c = Context({ + 'taglist': tag_list, + }) + + return HttpResponse(t.render(c)) + +def tag(request, tag_name): + post_list = Post.objects.filter(tags__name=tag_name) + t = loader.get_template("blog/posts.html") + c = Context({ + 'postlist': post_list, + }) + + return HttpResponse(t.render(c)) diff --git a/links/__init__.py b/links/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/links/admin.py b/links/admin.py new file mode 100644 index 0000000..29b8674 --- /dev/null +++ b/links/admin.py @@ -0,0 +1,4 @@ +from links.models import Bookmark +from django.contrib import admin + +admin.site.register(Bookmark) diff --git a/links/models.py b/links/models.py new file mode 100644 index 0000000..50319a2 --- /dev/null +++ b/links/models.py @@ -0,0 +1,35 @@ +from django.db import models +from main.models import Tag, Activity +from django.db.models.signals import post_save, post_delete + +class Bookmark(models.Model): + url = models.URLField(primary_key=True, max_length=255) + date = models.DateTimeField(auto_now_add=True) + name = models.CharField(max_length=255) + description = models.TextField() +# tags = models.ManyToManyField(Tag, null=True, blank=True) + priority = models.IntegerField(null=True, blank=True) + + def __unicode__(self): + return self.name + +def bookmark_saved_callback(sender, **kwargs): + if kwargs['created']: + acttype = 'add' + else: + acttype = 'edit' + + a = Activity(actcategory='link', + actdescription=kwargs["instance"].name, + acttype = acttype, + objpk = kwargs["instance"].pk) + a.save() + +def bookmark_deleted_callback(sender, **kwargs): + a = Activity(actcategory='link', + actdescription=kwargs["instance"].name, + acttype = 'delete') + a.save() + +post_save.connect(bookmark_saved_callback, sender=Bookmark) +post_delete.connect(bookmark_deleted_callback, sender=Bookmark) diff --git a/links/tests.py b/links/tests.py new file mode 100644 index 0000000..501deb7 --- /dev/null +++ b/links/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/links/urls.py b/links/urls.py new file mode 100644 index 0000000..25d8cc8 --- /dev/null +++ b/links/urls.py @@ -0,0 +1,5 @@ +from django.conf.urls.defaults import patterns + +urlpatterns = patterns('links.views', + (r'^$', 'index'), +) diff --git a/links/views.py b/links/views.py new file mode 100644 index 0000000..fe0d89d --- /dev/null +++ b/links/views.py @@ -0,0 +1,12 @@ +from links.models import Bookmark +from django.http import HttpResponse +from django.template import Context, loader + +def index(request): + bookmark_list = Bookmark.objects.all().order_by("-date")[:100] + t = loader.get_template("links/links.html") + c = Context({ + 'bookmarklist': bookmark_list, + }) + + return HttpResponse(t.render(c)) diff --git a/local_settings.py.example b/local_settings.py.example new file mode 100644 index 0000000..6a166a7 --- /dev/null +++ b/local_settings.py.example @@ -0,0 +1,15 @@ +DEBUG = False + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': '', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '00000000000000000000000000000000000000000000000000' diff --git a/main/__init__.py b/main/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/admin.py b/main/admin.py new file mode 100644 index 0000000..093f769 --- /dev/null +++ b/main/admin.py @@ -0,0 +1,4 @@ +from main.models import Tag +from django.contrib import admin + +admin.site.register(Tag) diff --git a/main/models.py b/main/models.py new file mode 100644 index 0000000..8ecddec --- /dev/null +++ b/main/models.py @@ -0,0 +1,24 @@ +from django.db import models + +class Tag(models.Model): + name = models.CharField(primary_key=True, max_length=200) + + def __unicode__(self): + return self.name + +class Activity(models.Model): + ACTCATEGORY_CHOICES = ( + ('blog', 'Blog post'), + ('project', 'Project page'), + ('link', 'Link'), + ) + ACTTYPE_CHOICES = ( + ('add', 'Add'), + ('edit', 'Edit'), + ('delete', 'Delete'), + ) + date = models.DateTimeField(auto_now=True) + actcategory = models.CharField(max_length=100, choices=ACTCATEGORY_CHOICES) + actdescription = models.CharField(max_length=500) + acttype = models.CharField(max_length=6) + objpk = models.CharField(max_length=300, null=True) diff --git a/main/signals.py b/main/signals.py new file mode 100644 index 0000000..e69de29 diff --git a/main/tests.py b/main/tests.py new file mode 100644 index 0000000..2247054 --- /dev/null +++ b/main/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/main/urls.py b/main/urls.py new file mode 100644 index 0000000..9f861b5 --- /dev/null +++ b/main/urls.py @@ -0,0 +1,4 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('main.views', + (r'^$', 'index')) diff --git a/main/views.py b/main/views.py new file mode 100644 index 0000000..91e20dd --- /dev/null +++ b/main/views.py @@ -0,0 +1,13 @@ +from django.http import HttpResponse +from django.shortcuts import render_to_response +from django.template import Context, loader +from main.models import Activity + +def index(request): + activity_list = Activity.objects.all().order_by("-date")[:5] + t = loader.get_template("home.html") + c = Context({ + "activitylist": activity_list, + }) + + return HttpResponse(t.render(c)) diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..6a43c99 --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python2 +from django.core.management import execute_manager +try: + import settings # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) + sys.exit(1) + +if __name__ == "__main__": + execute_manager(settings) diff --git a/projects/__init__.py b/projects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/projects/admin.py b/projects/admin.py new file mode 100644 index 0000000..b5ec7d4 --- /dev/null +++ b/projects/admin.py @@ -0,0 +1,6 @@ +from projects.models import Project, Language, Screenshot +from django.contrib import admin + +admin.site.register(Project) +admin.site.register(Language) +admin.site.register(Screenshot) diff --git a/projects/models.py b/projects/models.py new file mode 100644 index 0000000..4b2b49a --- /dev/null +++ b/projects/models.py @@ -0,0 +1,59 @@ +from django.db import models +from main.models import Tag, Activity +from django.db.models.signals import post_save, post_delete + +class Language(models.Model): + name = models.CharField(max_length=100) + + def __unicode__(self): + return self.name + +class Screenshot(models.Model): + url = models.URLField(max_length=255) + description = models.CharField(max_length=300) + + def __unicode__(self): + return self.description + +class Project(models.Model): + STATUS_CHOICES = ( + ('active', "Active"), + ('onhold', "On Hold"), + ('dropped', "Dropped"), + ) + + slug = models.SlugField(max_length=255, primary_key=True) + name = models.CharField(max_length=300) + status = models.CharField(max_length=8, choices=STATUS_CHOICES) + tagline = models.CharField(max_length=140, null=True, blank=True) + languages = models.ManyToManyField(Language, null=True, blank=True) + source_url = models.URLField(max_length=255, null=True, blank=True) + bugtracker_url = models.URLField(max_length=255, null=True, blank=True) + wiki_url = models.URLField(max_length=255, null=True, blank=True) + description = models.TextField() + screenshots = models.ForeignKey(Screenshot, null=True, blank=True) +# tags = models.ManyToManyField(Tag, null=True, blank=True) + + def __unicode__(self): + return self.name + +def project_saved_callback(sender, **kwargs): + if kwargs['created']: + acttype = 'add' + else: + acttype = 'edit' + + a = Activity(actcategory='project', + actdescription=kwargs["instance"].name, + acttype = acttype, + objpk = kwargs["instance"].pk) + a.save() + +def project_deleted_callback(sender, **kwargs): + a = Activity(actcategory='project', + actdescription=kwargs["instance"].name, + acttype = 'delete') + a.save() + +post_save.connect(project_saved_callback, sender=Project) +post_delete.connect(project_deleted_callback, sender=Project) diff --git a/projects/urls.py b/projects/urls.py new file mode 100644 index 0000000..053ab5b --- /dev/null +++ b/projects/urls.py @@ -0,0 +1,13 @@ +from django.conf.urls.defaults import * +from projects.models import Project, Language + +project_info_dict = { + 'queryset': Project.objects.all(), +} + +urlpatterns = patterns('', + (r'^$', + 'django.views.generic.list_detail.object_list', + project_info_dict), + (r'^(?P[\w-]+)/$', 'projects.views.project'), +) diff --git a/projects/views.py b/projects/views.py new file mode 100644 index 0000000..ad46ebd --- /dev/null +++ b/projects/views.py @@ -0,0 +1,24 @@ +from django.http import HttpResponse +from django.template import Context, loader +from projects.models import Project + +def project(request, object_id): + project = Project.objects.get(pk=object_id) + stats_dict = { + "Status": project.get_status_display(), + "Languages": ", ".join([language.name for language in project.languages.all()]), + } + links_dict = { + "Source": project.source_url, + "Bugtracker": project.bugtracker_url, + "Wiki": project.wiki_url, + } + + t = loader.get_template("projects/project_detail.html") + c = Context({ + "object": project, + "stats": stats_dict, + "links": links_dict, + }) + + return HttpResponse(t.render(c)) diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..2ef7e8f --- /dev/null +++ b/settings.py @@ -0,0 +1,91 @@ +# Django settings for website project. +import os, sys +from local_settings import * + +DEPLOY_PATH = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, DEPLOY_PATH) + +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + ('Tom Willemsen', 'ryuslash@gmail.com'), +) + +MANAGERS = ADMINS + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/Brussels' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a +# trailing slash. +# Examples: "http://foo.com/media/", "/media/". +ADMIN_MEDIA_PREFIX = '/media/' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', +) + +ROOT_URLCONF = 'urls' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. + '%s/templates' % DEPLOY_PATH, +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + # Uncomment the next line to enable the admin: + 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + # 'django.contrib.admindocs', + 'main', + 'blog', + 'projects', + 'links', +) diff --git a/templates/admin/login.html b/templates/admin/login.html new file mode 100644 index 0000000..eba271f --- /dev/null +++ b/templates/admin/login.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block extrastyle %}{% load adminmedia %}{{ block.super }}{% endblock %} + +{% block bodyclass %}login{% endblock %} + +{% block nav-global %}{% endblock %} + +{% block content_title %}{% endblock %} + +{% block breadcrumbs %}{% endblock %} + +{% block content %} +{% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %} +

+{% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %} +

+{% endif %} + +{% if form.non_field_errors or form.this_is_the_login_form.errors %} +{% for error in form.non_field_errors|add:form.this_is_the_login_form.errors %} +

+ {{ error }} +

+{% endfor %} +{% endif %} + +
+
{% csrf_token %} +
+ {% if not form.this_is_the_login_form.errors %}{{ form.username.errors }}{% endif %} + {{ form.username }} +
+
+ {% if not form.this_is_the_login_form.errors %}{{ form.password.errors }}{% endif %} + {{ form.password }} + + +
+
+ +
+
+ + +
+{% endblock %} diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..e910a76 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,44 @@ + + + + + + ryuslash | {% block subtitle %}linux and coding{% endblock %} + + {% block extrastyle %}{% endblock %} + + +
+ +
+
+ +
+ {% block content %} + {% endblock %} +
+
+
+ +
+ + diff --git a/templates/blog/base.html b/templates/blog/base.html new file mode 100644 index 0000000..2eadc88 --- /dev/null +++ b/templates/blog/base.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block subtitle %} + blog +{% endblock %} diff --git a/templates/blog/posts.html b/templates/blog/posts.html new file mode 100644 index 0000000..d9bc72d --- /dev/null +++ b/templates/blog/posts.html @@ -0,0 +1,42 @@ + + +{% extends "blog/base.html" %} + +{% block content %} + {% if postlist %} + {% for post in postlist %} +
+ + {% autoescape off %} + {{ post.body|linebreaksbr }} + {% endautoescape %} + +
+ {% endfor %} + + + {% else %} + Yeah I know, I'm boring. + {% endif %} +{% endblock %} diff --git a/templates/blog/tags.html b/templates/blog/tags.html new file mode 100644 index 0000000..a180634 --- /dev/null +++ b/templates/blog/tags.html @@ -0,0 +1,19 @@ + + +{% extends "blog/base.html" %} + +{% block subtitle %} + blog/tags +{% endblock %} + +{% block content %} +
    + {% for tag in taglist %} +
  • + {{ tag.name }} +
  • + {% empty %} + Sorry, no tags here. + {% endfor %} +
+{% endblock %} diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..a34a0d8 --- /dev/null +++ b/templates/home.html @@ -0,0 +1,88 @@ +{% extends "base.html" %} + +{% block content %} + This will, hopefully, eventually, become my website. + Rejoice! +

+ Some places you can already find me: +

    +
  • + Gitorious + - This is where I host most of my projects. +
  • +
  • + Github + - Sometimes I host projects here as well, but I prefer + Gitorious. +
  • +
  • + Stack Overflow + - Don't really do much there, but I did just get my + first reputation points. +
    + + profile for slash at Stack Overflow, Q&A
+                    for professional and enthusiast
+                    programmers + +
  • +
+

+ + {% for activity in activitylist %} + + {% endfor %} +{% endblock %} diff --git a/templates/links/links.html b/templates/links/links.html new file mode 100644 index 0000000..b911d80 --- /dev/null +++ b/templates/links/links.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} + +{% block subtitle %} + links +{% endblock %} + +{% block content %} +
+
+ links +
+ {% if bookmarklist %} + {% for link in bookmarklist %} + {{ link.name }}
+ {% endfor %} + {% else %} + No links, no where... + {% endif %} +
+{% endblock %} diff --git a/templates/projects/base.html b/templates/projects/base.html new file mode 100644 index 0000000..d3654cc --- /dev/null +++ b/templates/projects/base.html @@ -0,0 +1,3 @@ + + +{% extends "base.html" %} diff --git a/templates/projects/project_detail.html b/templates/projects/project_detail.html new file mode 100644 index 0000000..1c19f4f --- /dev/null +++ b/templates/projects/project_detail.html @@ -0,0 +1,52 @@ + + +{% extends "projects/base.html" %} + +{% block subtitle %} + projects/{{ object.name }} +{% endblock %} + +{% block content %} +
+
+ {{ object.name }} + {{ object.tagline }} +
+ + +

+ {% autoescape off %} + {{ object.description|linebreaksbr }} + {% endautoescape %} +

+
+ +
+
+ Stats +
+ {% for key, value in stats.items %} + {% if value %} + {{ key }}: {{ value }}
+ {% endif %} + {% endfor %} +
+ +
+
+ Links +
+ {% for key, value in links.items %} + {% if value %} + {{ key }}
+ {% endif %} + {% endfor %} +
+ + {% if object.screenshots %} +

+ Screenshots here +

+ {% endif %} + +{% endblock %} diff --git a/templates/projects/project_list.html b/templates/projects/project_list.html new file mode 100644 index 0000000..1ab750c --- /dev/null +++ b/templates/projects/project_list.html @@ -0,0 +1,20 @@ + + +{% extends "projects/base.html" %} + +{% block subtitle %} + projects +{% endblock %} + +{% block content %} + {% if object_list %} +
+ {% for project in object_list %} +
{{ project.name }}
+
{{ project.tagline }}
+ {% endfor %} +
+ {% else %} + Well, you know me, I'm lazy. Got nothing going on. + {% endif %} +{% endblock %} diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..1c46129 --- /dev/null +++ b/urls.py @@ -0,0 +1,19 @@ +from django.conf.urls.defaults import * +from settings import DEPLOY_PATH, DEBUG + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +admin.autodiscover() + +urlpatterns = patterns('', + (r'^blog/', include("blog.urls")), + (r'^projects/', include("projects.urls")), + (r'^links/', include("links.urls")), + (r'^admin/', include(admin.site.urls)), + (r'^', include("main.urls")), +) + +if DEBUG: + urlpatterns += patterns('', + (r'^static/(?P.*)$', 'django.views.static.serve', {'document_root': '%s/static' % DEPLOY_PATH}) +) From 825d57a222b068d73fe85ad89e3f141b08b27f28 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 17 Oct 2011 02:12:10 +0200 Subject: [PATCH 02/21] Add static files --- .gitignore | 1 - static/css/login.css | 13 +++ static/css/main.css | 200 ++++++++++++++++++++++++++++++++++++++++ static/img/logo.png | Bin 0 -> 15931 bytes static/img/logo_big.png | Bin 0 -> 71796 bytes 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 static/css/login.css create mode 100644 static/css/main.css create mode 100644 static/img/logo.png create mode 100644 static/img/logo_big.png diff --git a/.gitignore b/.gitignore index db82c7d..04e93be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ *.pyc local_settings.py -static .toudou test.db diff --git a/static/css/login.css b/static/css/login.css new file mode 100644 index 0000000..a9ab3ed --- /dev/null +++ b/static/css/login.css @@ -0,0 +1,13 @@ +.form-row label { + float: left; + width: 9em; +} + +p.errornote { + margin: 0; + color: #CC0000; +} + +.errorlist { + color: #CC0000; +} diff --git a/static/css/main.css b/static/css/main.css new file mode 100644 index 0000000..1dc5183 --- /dev/null +++ b/static/css/main.css @@ -0,0 +1,200 @@ +* { + border : 0; + margin : 0; + padding : 0; +} + +a { + color : #FFC000; + text-decoration : none; +} + +a:hover { + text-decoration : underline; +} + +a:visited { + color : #FF8A00; +} + +body { + background-color : #000000; + color : #000000; + font-family : sans, sans-serif; + padding-left : 10px; +} + +dd { + margin-left: 40px; +} + +p { + margin : 1em 0px; +} + +ul { + margin : 1em 0; + padding-left : 40px; +} + +#body { + background-color : #777; +} + +#container { + margin : 20px auto; + width : 700px; +} + +#container #footer { + background-color : #0C191C; + color : #EEEEEC; + font-size : 10px; + padding-left : 5px; +} + +#container #header { + border-top-left-radius : 30px; + border-top-right-radius : 30px; + -moz-border-radius-topleft : 30px; + -moz-border-radius-topright : 30px; +} + +#content { + margin-left : 100px; + padding-bottom : 1px; + padding-left : 20px; + padding-right : 20px; +} + +#content .container { + color : #EEEEEC; +} + +#content .container .header { + background-color : transparent; + padding-bottom : 5px; + padding-left : 0; + padding-top : 5px; +} + +#content .container .header a { + color : inherit; + text-decoration : none; +} + +#content .container .header span.tagline { + color: #EEEEEC; + font-size: 12px; +} + +#content .container .header span.title { + background-color : #2E3436; + left : -5px; + padding : 5px; + position : relative; + top : -5px; +} + +#header { + background-color : #252A2B; +} + +#logo { + float : left; + height : 100px; + margin : -13px 20px 23px 5px; + width : 100px; +} + +#ryu { + color : #F57900; +} + +#slash { + position: relative; + top: 5px; +} + +#menu { + margin-left : -5px; + float : left; + width : 100px; +} + +#menu a { + color : #FFC000; + text-decoration : none; +} + +#title { + color : #EEEEEC; + height : 100px; + line-height : 100px; +} + +#title sup { + font-size : 11px; + position : relative; + top : 5px; +} + +.activity_even { + background-color : #2E3436; +} + +.activity_even, .activity_uneven { + border-bottom : 1px solid #444444; + color : #EEEEEC; + font-size : 12px; + margin: 0 20px; + padding : 2px 0 2px 5px; +} + +.activity_last { + border-bottom : none; +} + +.activity_uneven { + background-color : #0C191C; +} + +.container { + background-color : #0C191C; + border : 1px solid #2E3436; + margin-bottom : 20px; + padding : 2px 5px; + padding-left : 10px; +} + +.clear { + clear : both; +} + +.clearleft { + clear : left; +} + +.container .header { + background-color : #2E3436; + color : #F57900; + font-weight : bold; + margin : -2px -5px 0 -10px; + padding-left : 5px; +} + +.container .footer { + background-color : #2E3436; + color : #0C191C; + font-size : 10px; + margin : 0 -5px -2px -10px; + padding-left : 5px; +} + +.navigation a { + color : #FFC000; +} + +.navigation a.next { + float : right; +} diff --git a/static/img/logo.png b/static/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a451578dcd39e9cd6d46f1cd29abd9f08a5c7957 GIT binary patch literal 15931 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 literal 0 HcmV?d00001 diff --git a/static/img/logo_big.png b/static/img/logo_big.png new file mode 100644 index 0000000000000000000000000000000000000000..d6ac0d9e00f2dd70b4b381a0b8e019d5856c4986 GIT binary patch literal 71796 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 literal 0 HcmV?d00001 From 62cc00f06250478a40cf75439a33f871c6e85057 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 17 Oct 2011 02:29:21 +0200 Subject: [PATCH 03/21] Update home page --- templates/home.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/templates/home.html b/templates/home.html index a34a0d8..e5c2fed 100644 --- a/templates/home.html +++ b/templates/home.html @@ -7,13 +7,12 @@ Some places you can already find me:
  • - Gitorious - - This is where I host most of my projects. + Diaspora* - I'm here + all the time.
  • - Github - - Sometimes I host projects here as well, but I prefer - Gitorious. + Identi.ca - Don't post + much, but I'm usually there.
  • Stack Overflow From d7f99435105fd28e730427c0e494c9607d3803a3 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 17 Oct 2011 02:57:42 +0200 Subject: [PATCH 04/21] Removed links module --- links/__init__.py | 0 links/admin.py | 4 ---- links/models.py | 35 ----------------------------------- links/tests.py | 16 ---------------- links/urls.py | 5 ----- links/views.py | 12 ------------ settings.py | 1 - templates/base.html | 1 - templates/links/links.html | 20 -------------------- urls.py | 1 - 10 files changed, 95 deletions(-) delete mode 100644 links/__init__.py delete mode 100644 links/admin.py delete mode 100644 links/models.py delete mode 100644 links/tests.py delete mode 100644 links/urls.py delete mode 100644 links/views.py delete mode 100644 templates/links/links.html diff --git a/links/__init__.py b/links/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/links/admin.py b/links/admin.py deleted file mode 100644 index 29b8674..0000000 --- a/links/admin.py +++ /dev/null @@ -1,4 +0,0 @@ -from links.models import Bookmark -from django.contrib import admin - -admin.site.register(Bookmark) diff --git a/links/models.py b/links/models.py deleted file mode 100644 index 50319a2..0000000 --- a/links/models.py +++ /dev/null @@ -1,35 +0,0 @@ -from django.db import models -from main.models import Tag, Activity -from django.db.models.signals import post_save, post_delete - -class Bookmark(models.Model): - url = models.URLField(primary_key=True, max_length=255) - date = models.DateTimeField(auto_now_add=True) - name = models.CharField(max_length=255) - description = models.TextField() -# tags = models.ManyToManyField(Tag, null=True, blank=True) - priority = models.IntegerField(null=True, blank=True) - - def __unicode__(self): - return self.name - -def bookmark_saved_callback(sender, **kwargs): - if kwargs['created']: - acttype = 'add' - else: - acttype = 'edit' - - a = Activity(actcategory='link', - actdescription=kwargs["instance"].name, - acttype = acttype, - objpk = kwargs["instance"].pk) - a.save() - -def bookmark_deleted_callback(sender, **kwargs): - a = Activity(actcategory='link', - actdescription=kwargs["instance"].name, - acttype = 'delete') - a.save() - -post_save.connect(bookmark_saved_callback, sender=Bookmark) -post_delete.connect(bookmark_deleted_callback, sender=Bookmark) diff --git a/links/tests.py b/links/tests.py deleted file mode 100644 index 501deb7..0000000 --- a/links/tests.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" - -from django.test import TestCase - - -class SimpleTest(TestCase): - def test_basic_addition(self): - """ - Tests that 1 + 1 always equals 2. - """ - self.assertEqual(1 + 1, 2) diff --git a/links/urls.py b/links/urls.py deleted file mode 100644 index 25d8cc8..0000000 --- a/links/urls.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.conf.urls.defaults import patterns - -urlpatterns = patterns('links.views', - (r'^$', 'index'), -) diff --git a/links/views.py b/links/views.py deleted file mode 100644 index fe0d89d..0000000 --- a/links/views.py +++ /dev/null @@ -1,12 +0,0 @@ -from links.models import Bookmark -from django.http import HttpResponse -from django.template import Context, loader - -def index(request): - bookmark_list = Bookmark.objects.all().order_by("-date")[:100] - t = loader.get_template("links/links.html") - c = Context({ - 'bookmarklist': bookmark_list, - }) - - return HttpResponse(t.render(c)) diff --git a/settings.py b/settings.py index 2ef7e8f..5a6641e 100644 --- a/settings.py +++ b/settings.py @@ -87,5 +87,4 @@ INSTALLED_APPS = ( 'main', 'blog', 'projects', - 'links', ) diff --git a/templates/base.html b/templates/base.html index e910a76..01ec076 100644 --- a/templates/base.html +++ b/templates/base.html @@ -25,7 +25,6 @@ home
    blog
    projects
    - links {% block submenu %}{% endblock %} diff --git a/templates/links/links.html b/templates/links/links.html deleted file mode 100644 index b911d80..0000000 --- a/templates/links/links.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "base.html" %} - -{% block subtitle %} - links -{% endblock %} - -{% block content %} -
    -
    - links -
    - {% if bookmarklist %} - {% for link in bookmarklist %} - {{ link.name }}
    - {% endfor %} - {% else %} - No links, no where... - {% endif %} -
    -{% endblock %} diff --git a/urls.py b/urls.py index 1c46129..a5e253d 100644 --- a/urls.py +++ b/urls.py @@ -8,7 +8,6 @@ admin.autodiscover() urlpatterns = patterns('', (r'^blog/', include("blog.urls")), (r'^projects/', include("projects.urls")), - (r'^links/', include("links.urls")), (r'^admin/', include(admin.site.urls)), (r'^', include("main.urls")), ) From e533b3b82e254e2c22ed40a570b5e8b31a1f126b Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 29 Oct 2011 01:37:55 +0200 Subject: [PATCH 05/21] First try at an ATOM feed --- blog/urls.py | 1 + blog/views.py | 8 ++++++++ templates/blog/base.html | 14 ++++++++++++++ templates/blog/rss.xml | 25 +++++++++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 templates/blog/rss.xml diff --git a/blog/urls.py b/blog/urls.py index c4137ed..a21c56a 100644 --- a/blog/urls.py +++ b/blog/urls.py @@ -6,4 +6,5 @@ urlpatterns = patterns('blog.views', (r'^post/(?P\d+)/$', 'post'), (r'^tags/$', 'tags'), (r'^tag/(?P[\w_]+)/$', 'tag'), + (r'^atom/$', 'atom'), ) diff --git a/blog/views.py b/blog/views.py index 06a4aba..92ac55e 100644 --- a/blog/views.py +++ b/blog/views.py @@ -27,6 +27,14 @@ def index(request, page=0): return direct_to_template(request, "blog/posts.html", c) +def atom(request): + post_list = Post.objects.all().order_by("-postdate")[0:15] + c = { + 'postlist': post_list, + } + + return direct_to_template(request, "blog/rss.xml", c) + def post(request, post_id): post = Post.objects.filter(pk=post_id) t = loader.get_template("blog/posts.html") diff --git a/templates/blog/base.html b/templates/blog/base.html index 2eadc88..e5caf88 100644 --- a/templates/blog/base.html +++ b/templates/blog/base.html @@ -3,3 +3,17 @@ {% block subtitle %} blog {% endblock %} + +{% block extrastyle %} + +{% endblock %} + +{% block submenu %} +
    +
    + blog +
    + feed +
    +{% endblock %} diff --git a/templates/blog/rss.xml b/templates/blog/rss.xml new file mode 100644 index 0000000..9cc6df3 --- /dev/null +++ b/templates/blog/rss.xml @@ -0,0 +1,25 @@ + + + ryuslash.org + + + http://ryuslash.org/blog/ + + Tom Willemsen + + 2011-10-29T23:16:00+01:00 + + {% for post in postlist %} + + {{ post.subject }} + + http://ryuslash.org/blog/post/{{ post.pk }}/ + {{ post.postdate|date:"c" }} + +
    + {{ post.body|linebreaksbr }} +
    +
    +
    + {% endfor %} +
    From 3ec79710ca046b2c172eb77679eb5e2983460a1a Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Fri, 4 Nov 2011 22:10:49 +0100 Subject: [PATCH 06/21] Render html pages in templates/html_pages --- pages/__init__.py | 0 pages/models.py | 3 +++ pages/urls.py | 5 +++++ pages/views.py | 18 ++++++++++++++++++ templates/pages/index.html | 5 +++++ urls.py | 4 ++++ 6 files changed, 35 insertions(+) create mode 100644 pages/__init__.py create mode 100644 pages/models.py create mode 100644 pages/urls.py create mode 100644 pages/views.py create mode 100644 templates/pages/index.html diff --git a/pages/__init__.py b/pages/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pages/models.py b/pages/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/pages/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/pages/urls.py b/pages/urls.py new file mode 100644 index 0000000..1c0cf82 --- /dev/null +++ b/pages/urls.py @@ -0,0 +1,5 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('pages.views', + (r'^(?P.+)/$', 'index'), +) diff --git a/pages/views.py b/pages/views.py new file mode 100644 index 0000000..2f902a6 --- /dev/null +++ b/pages/views.py @@ -0,0 +1,18 @@ +import os.path + +from django.http import Http404 +from django.views.generic.simple import direct_to_template + +from settings import DEPLOY_PATH + +def index(request, page): + + template = 'html_pages/%s/index.html' % page + if not os.path.exists('%s/templates/%s' % (DEPLOY_PATH, template): + raise Http404 + + c = { + "page": template, + } + + return direct_to_template(request, "pages/index.html", c) diff --git a/templates/pages/index.html b/templates/pages/index.html new file mode 100644 index 0000000..18988f9 --- /dev/null +++ b/templates/pages/index.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block content %} +{% include page %} +{% endblock %} diff --git a/urls.py b/urls.py index a5e253d..3b24bf7 100644 --- a/urls.py +++ b/urls.py @@ -15,4 +15,8 @@ urlpatterns = patterns('', if DEBUG: urlpatterns += patterns('', (r'^static/(?P.*)$', 'django.views.static.serve', {'document_root': '%s/static' % DEPLOY_PATH}) + ) + +urlpatterns += patterns('', + (r'^', include("pages.urls")) ) From 7e3102b7603142078578b0b8dd1690a24e4d7bcd Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 00:29:30 +0100 Subject: [PATCH 07/21] Fix syntax errors --- pages/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/views.py b/pages/views.py index 2f902a6..7a44701 100644 --- a/pages/views.py +++ b/pages/views.py @@ -8,7 +8,7 @@ from settings import DEPLOY_PATH def index(request, page): template = 'html_pages/%s/index.html' % page - if not os.path.exists('%s/templates/%s' % (DEPLOY_PATH, template): + if not os.path.exists('%s/templates/%s' % (DEPLOY_PATH, template)): raise Http404 c = { From 3ae51caab712c4c60072f01cd8ce2e09c28300be Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 00:31:22 +0100 Subject: [PATCH 08/21] Add pages to installed apps --- settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.py b/settings.py index 5a6641e..50e4d11 100644 --- a/settings.py +++ b/settings.py @@ -87,4 +87,5 @@ INSTALLED_APPS = ( 'main', 'blog', 'projects', + 'pages', ) From fc51d7160df5ce97bfeba64a5af8efe2962223dd Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 00:33:33 +0100 Subject: [PATCH 09/21] Add parse_markdown command --- local_settings.py.example | 1 + pages/management/__init__.py | 0 pages/management/commands/__init__.py | 0 pages/management/commands/parse_markdown.py | 31 +++++++++++++++++++++ templates/.gitignore | 1 + 5 files changed, 33 insertions(+) create mode 100644 pages/management/__init__.py create mode 100644 pages/management/commands/__init__.py create mode 100644 pages/management/commands/parse_markdown.py create mode 100644 templates/.gitignore diff --git a/local_settings.py.example b/local_settings.py.example index 6a166a7..fe6c1aa 100644 --- a/local_settings.py.example +++ b/local_settings.py.example @@ -1,4 +1,5 @@ DEBUG = False +MARKDOWN_PATH = '' DATABASES = { 'default': { diff --git a/pages/management/__init__.py b/pages/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pages/management/commands/__init__.py b/pages/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py new file mode 100644 index 0000000..8c193df --- /dev/null +++ b/pages/management/commands/parse_markdown.py @@ -0,0 +1,31 @@ +import os +import markdown + +from django.core.management.base import BaseCommand, CommandError + +from settings import MARKDOWN_PATH, DEPLOY_PATH + +class Command(BaseCommand): + help = 'Parse markdown files in %s' % MARKDOWN_PATH + + def handle(self, *args, **options): + for root, dirs, files in os.walk(MARKDOWN_PATH): + for file in files: + subdir = root.replace(MARKDOWN_PATH, "") + mdfile = '%s/%s' % (root, file) + mdname = '%s/%s' % (subdir, os.path.splitext(file)[0]) + htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) + htmlfile = '%s/index.html' % htmlpath + + if os.path.exists(mdfile) and not os.path.exists(htmlfile) \ + or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile): + + if not os.path.exists(htmlpath): + os.makedirs(htmlpath) + + md = markdown.Markdown() + print 'Converting ', mdname, '-->', htmlfile, + wikiExtension = 'wikilinks(base_url=%s/)' % subdir + markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", extensions=[wikiExtension]) + print ' ... succeeded' + diff --git a/templates/.gitignore b/templates/.gitignore new file mode 100644 index 0000000..c46f106 --- /dev/null +++ b/templates/.gitignore @@ -0,0 +1 @@ +html_pages From f426a2f8efd7b91219e28514976a11ec55e4bf28 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 02:17:51 +0100 Subject: [PATCH 10/21] Only parse mdwn files --- pages/management/commands/parse_markdown.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py index 8c193df..105b004 100644 --- a/pages/management/commands/parse_markdown.py +++ b/pages/management/commands/parse_markdown.py @@ -13,11 +13,13 @@ class Command(BaseCommand): for file in files: subdir = root.replace(MARKDOWN_PATH, "") mdfile = '%s/%s' % (root, file) - mdname = '%s/%s' % (subdir, os.path.splitext(file)[0]) + mdtuple = os.path.splitext(file) + mdname = '%s/%s' % (subdir, mdtuple[0]) htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) htmlfile = '%s/index.html' % htmlpath - if os.path.exists(mdfile) and not os.path.exists(htmlfile) \ + if mdtuple[1] == '.mdwn' \ + and os.path.exists(mdfile) and not os.path.exists(htmlfile) \ or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile): if not os.path.exists(htmlpath): @@ -26,6 +28,8 @@ class Command(BaseCommand): md = markdown.Markdown() print 'Converting ', mdname, '-->', htmlfile, wikiExtension = 'wikilinks(base_url=%s/)' % subdir - markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", extensions=[wikiExtension]) + markdown.markdownFromFile(input=mdfile, output=htmlfile, + encoding="utf-8", + extensions=[wikiExtension]) print ' ... succeeded' From 186d47fe849e03766427557a14ea1cd44c2c5623 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 02:23:26 +0100 Subject: [PATCH 11/21] Only check time if it exists --- pages/management/commands/parse_markdown.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py index 105b004..500087a 100644 --- a/pages/management/commands/parse_markdown.py +++ b/pages/management/commands/parse_markdown.py @@ -18,9 +18,9 @@ class Command(BaseCommand): htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) htmlfile = '%s/index.html' % htmlpath - if mdtuple[1] == '.mdwn' \ - and os.path.exists(mdfile) and not os.path.exists(htmlfile) \ - or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile): + if mdtuple[1] == '.mdwn' and os.path.exists(mdfile) \ + and (not os.path.exists(htmlfile) \ + or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile)): if not os.path.exists(htmlpath): os.makedirs(htmlpath) @@ -28,8 +28,7 @@ class Command(BaseCommand): md = markdown.Markdown() print 'Converting ', mdname, '-->', htmlfile, wikiExtension = 'wikilinks(base_url=%s/)' % subdir - markdown.markdownFromFile(input=mdfile, output=htmlfile, - encoding="utf-8", + markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", extensions=[wikiExtension]) print ' ... succeeded' From 0e14ef7f7c336d138c31a83845039cbea8dce4af Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 02:50:21 +0100 Subject: [PATCH 12/21] Add some verbosity --- pages/management/commands/parse_markdown.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py index 500087a..38fc7ea 100644 --- a/pages/management/commands/parse_markdown.py +++ b/pages/management/commands/parse_markdown.py @@ -18,6 +18,13 @@ class Command(BaseCommand): htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) htmlfile = '%s/index.html' % htmlpath + if options['verbosity'] == '3': + print 'Subdir: ', subdir + print 'Mdfile: ', mdfile + print 'Mdtuple: ', mdtuple + print 'Htmlpath: ', htmlpath + print 'Htmlfile: ', htmlfile + if mdtuple[1] == '.mdwn' and os.path.exists(mdfile) \ and (not os.path.exists(htmlfile) \ or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile)): From 528737be805c61ee3ccda767c98920ec5e14f928 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 03:50:48 +0100 Subject: [PATCH 13/21] Skip .git dir --- pages/management/commands/parse_markdown.py | 51 +++++++++++---------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py index 38fc7ea..4b2e774 100644 --- a/pages/management/commands/parse_markdown.py +++ b/pages/management/commands/parse_markdown.py @@ -5,37 +5,40 @@ from django.core.management.base import BaseCommand, CommandError from settings import MARKDOWN_PATH, DEPLOY_PATH +ignore_dir = '.git' + class Command(BaseCommand): help = 'Parse markdown files in %s' % MARKDOWN_PATH def handle(self, *args, **options): for root, dirs, files in os.walk(MARKDOWN_PATH): - for file in files: - subdir = root.replace(MARKDOWN_PATH, "") - mdfile = '%s/%s' % (root, file) - mdtuple = os.path.splitext(file) - mdname = '%s/%s' % (subdir, mdtuple[0]) - htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) - htmlfile = '%s/index.html' % htmlpath + if ignore_dir not in root: + for file in files: + subdir = root.replace(MARKDOWN_PATH, "") + mdfile = '%s/%s' % (root, file) + mdtuple = os.path.splitext(file) + mdname = '%s/%s' % (subdir, mdtuple[0]) + htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) + htmlfile = '%s/index.html' % htmlpath - if options['verbosity'] == '3': - print 'Subdir: ', subdir - print 'Mdfile: ', mdfile - print 'Mdtuple: ', mdtuple - print 'Htmlpath: ', htmlpath - print 'Htmlfile: ', htmlfile + if options['verbosity'] == '3': + print 'Subdir: ', subdir + print 'Mdfile: ', mdfile + print 'Mdtuple: ', mdtuple + print 'Htmlpath: ', htmlpath + print 'Htmlfile: ', htmlfile - if mdtuple[1] == '.mdwn' and os.path.exists(mdfile) \ - and (not os.path.exists(htmlfile) \ - or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile)): + if mdtuple[1] == '.mdwn' and os.path.exists(mdfile) \ + and (not os.path.exists(htmlfile) \ + or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile)): - if not os.path.exists(htmlpath): - os.makedirs(htmlpath) + if not os.path.exists(htmlpath): + os.makedirs(htmlpath) - md = markdown.Markdown() - print 'Converting ', mdname, '-->', htmlfile, - wikiExtension = 'wikilinks(base_url=%s/)' % subdir - markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", - extensions=[wikiExtension]) - print ' ... succeeded' + md = markdown.Markdown() + print 'Converting ', mdname, '-->', htmlfile, + wikiExtension = 'wikilinks(base_url=%s/)' % subdir + markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", + extensions=[wikiExtension]) + print ' ... succeeded' From 39f711d813c0300ca523d2726e5fd34496d0df08 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 13:06:58 +0100 Subject: [PATCH 14/21] Don't ignore any directories after all --- pages/management/commands/parse_markdown.py | 51 ++++++++++----------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py index 4b2e774..38fc7ea 100644 --- a/pages/management/commands/parse_markdown.py +++ b/pages/management/commands/parse_markdown.py @@ -5,40 +5,37 @@ from django.core.management.base import BaseCommand, CommandError from settings import MARKDOWN_PATH, DEPLOY_PATH -ignore_dir = '.git' - class Command(BaseCommand): help = 'Parse markdown files in %s' % MARKDOWN_PATH def handle(self, *args, **options): for root, dirs, files in os.walk(MARKDOWN_PATH): - if ignore_dir not in root: - for file in files: - subdir = root.replace(MARKDOWN_PATH, "") - mdfile = '%s/%s' % (root, file) - mdtuple = os.path.splitext(file) - mdname = '%s/%s' % (subdir, mdtuple[0]) - htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) - htmlfile = '%s/index.html' % htmlpath + for file in files: + subdir = root.replace(MARKDOWN_PATH, "") + mdfile = '%s/%s' % (root, file) + mdtuple = os.path.splitext(file) + mdname = '%s/%s' % (subdir, mdtuple[0]) + htmlpath = '%s/templates/html_pages/%s' % (DEPLOY_PATH, mdname) + htmlfile = '%s/index.html' % htmlpath - if options['verbosity'] == '3': - print 'Subdir: ', subdir - print 'Mdfile: ', mdfile - print 'Mdtuple: ', mdtuple - print 'Htmlpath: ', htmlpath - print 'Htmlfile: ', htmlfile + if options['verbosity'] == '3': + print 'Subdir: ', subdir + print 'Mdfile: ', mdfile + print 'Mdtuple: ', mdtuple + print 'Htmlpath: ', htmlpath + print 'Htmlfile: ', htmlfile - if mdtuple[1] == '.mdwn' and os.path.exists(mdfile) \ - and (not os.path.exists(htmlfile) \ - or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile)): + if mdtuple[1] == '.mdwn' and os.path.exists(mdfile) \ + and (not os.path.exists(htmlfile) \ + or os.path.getmtime(mdfile) > os.path.getmtime(htmlfile)): - if not os.path.exists(htmlpath): - os.makedirs(htmlpath) + if not os.path.exists(htmlpath): + os.makedirs(htmlpath) - md = markdown.Markdown() - print 'Converting ', mdname, '-->', htmlfile, - wikiExtension = 'wikilinks(base_url=%s/)' % subdir - markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", - extensions=[wikiExtension]) - print ' ... succeeded' + md = markdown.Markdown() + print 'Converting ', mdname, '-->', htmlfile, + wikiExtension = 'wikilinks(base_url=%s/)' % subdir + markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", + extensions=[wikiExtension]) + print ' ... succeeded' From 1766db73d97fe0b4e806bfc8e9e68d7400b4c935 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 13:55:14 +0100 Subject: [PATCH 15/21] Remove projects, is being handled by html_pages now --- projects/__init__.py | 0 projects/admin.py | 6 ----- projects/models.py | 59 -------------------------------------------- projects/urls.py | 13 ---------- projects/views.py | 24 ------------------ settings.py | 1 - templates/base.html | 2 +- urls.py | 1 - 8 files changed, 1 insertion(+), 105 deletions(-) delete mode 100644 projects/__init__.py delete mode 100644 projects/admin.py delete mode 100644 projects/models.py delete mode 100644 projects/urls.py delete mode 100644 projects/views.py diff --git a/projects/__init__.py b/projects/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/projects/admin.py b/projects/admin.py deleted file mode 100644 index b5ec7d4..0000000 --- a/projects/admin.py +++ /dev/null @@ -1,6 +0,0 @@ -from projects.models import Project, Language, Screenshot -from django.contrib import admin - -admin.site.register(Project) -admin.site.register(Language) -admin.site.register(Screenshot) diff --git a/projects/models.py b/projects/models.py deleted file mode 100644 index 4b2b49a..0000000 --- a/projects/models.py +++ /dev/null @@ -1,59 +0,0 @@ -from django.db import models -from main.models import Tag, Activity -from django.db.models.signals import post_save, post_delete - -class Language(models.Model): - name = models.CharField(max_length=100) - - def __unicode__(self): - return self.name - -class Screenshot(models.Model): - url = models.URLField(max_length=255) - description = models.CharField(max_length=300) - - def __unicode__(self): - return self.description - -class Project(models.Model): - STATUS_CHOICES = ( - ('active', "Active"), - ('onhold', "On Hold"), - ('dropped', "Dropped"), - ) - - slug = models.SlugField(max_length=255, primary_key=True) - name = models.CharField(max_length=300) - status = models.CharField(max_length=8, choices=STATUS_CHOICES) - tagline = models.CharField(max_length=140, null=True, blank=True) - languages = models.ManyToManyField(Language, null=True, blank=True) - source_url = models.URLField(max_length=255, null=True, blank=True) - bugtracker_url = models.URLField(max_length=255, null=True, blank=True) - wiki_url = models.URLField(max_length=255, null=True, blank=True) - description = models.TextField() - screenshots = models.ForeignKey(Screenshot, null=True, blank=True) -# tags = models.ManyToManyField(Tag, null=True, blank=True) - - def __unicode__(self): - return self.name - -def project_saved_callback(sender, **kwargs): - if kwargs['created']: - acttype = 'add' - else: - acttype = 'edit' - - a = Activity(actcategory='project', - actdescription=kwargs["instance"].name, - acttype = acttype, - objpk = kwargs["instance"].pk) - a.save() - -def project_deleted_callback(sender, **kwargs): - a = Activity(actcategory='project', - actdescription=kwargs["instance"].name, - acttype = 'delete') - a.save() - -post_save.connect(project_saved_callback, sender=Project) -post_delete.connect(project_deleted_callback, sender=Project) diff --git a/projects/urls.py b/projects/urls.py deleted file mode 100644 index 053ab5b..0000000 --- a/projects/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.conf.urls.defaults import * -from projects.models import Project, Language - -project_info_dict = { - 'queryset': Project.objects.all(), -} - -urlpatterns = patterns('', - (r'^$', - 'django.views.generic.list_detail.object_list', - project_info_dict), - (r'^(?P[\w-]+)/$', 'projects.views.project'), -) diff --git a/projects/views.py b/projects/views.py deleted file mode 100644 index ad46ebd..0000000 --- a/projects/views.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.http import HttpResponse -from django.template import Context, loader -from projects.models import Project - -def project(request, object_id): - project = Project.objects.get(pk=object_id) - stats_dict = { - "Status": project.get_status_display(), - "Languages": ", ".join([language.name for language in project.languages.all()]), - } - links_dict = { - "Source": project.source_url, - "Bugtracker": project.bugtracker_url, - "Wiki": project.wiki_url, - } - - t = loader.get_template("projects/project_detail.html") - c = Context({ - "object": project, - "stats": stats_dict, - "links": links_dict, - }) - - return HttpResponse(t.render(c)) diff --git a/settings.py b/settings.py index 50e4d11..f19b8e3 100644 --- a/settings.py +++ b/settings.py @@ -86,6 +86,5 @@ INSTALLED_APPS = ( # 'django.contrib.admindocs', 'main', 'blog', - 'projects', 'pages', ) diff --git a/templates/base.html b/templates/base.html index 01ec076..3c15623 100644 --- a/templates/base.html +++ b/templates/base.html @@ -24,7 +24,7 @@ home
    blog
    - projects
    + projects
    {% block submenu %}{% endblock %} diff --git a/urls.py b/urls.py index 3b24bf7..26aa007 100644 --- a/urls.py +++ b/urls.py @@ -7,7 +7,6 @@ admin.autodiscover() urlpatterns = patterns('', (r'^blog/', include("blog.urls")), - (r'^projects/', include("projects.urls")), (r'^admin/', include(admin.site.urls)), (r'^', include("main.urls")), ) From cee353fd4118e330c903fc4482a5c460aacbe65a Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 14:58:57 +0100 Subject: [PATCH 16/21] Add def_list extension --- pages/management/commands/parse_markdown.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pages/management/commands/parse_markdown.py b/pages/management/commands/parse_markdown.py index 38fc7ea..23ad2ec 100644 --- a/pages/management/commands/parse_markdown.py +++ b/pages/management/commands/parse_markdown.py @@ -34,8 +34,9 @@ class Command(BaseCommand): md = markdown.Markdown() print 'Converting ', mdname, '-->', htmlfile, - wikiExtension = 'wikilinks(base_url=%s/)' % subdir + wikilinks = 'wikilinks(base_url=%s/)' % subdir + def_list = 'def_list' markdown.markdownFromFile(input=mdfile, output=htmlfile, encoding="utf-8", - extensions=[wikiExtension]) + extensions=[wikilinks, def_list]) print ' ... succeeded' From 9c5a7e1198f98eaf9240779b945e2192eaa66f9d Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Sat, 5 Nov 2011 16:37:37 +0100 Subject: [PATCH 17/21] Style updates for markdown --- static/css/main.css | 4 ++++ templates/pages/index.html | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/static/css/main.css b/static/css/main.css index 1dc5183..96869c0 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -191,6 +191,10 @@ ul { padding-left : 5px; } +.markdown h3 { + margin: 1em 0; +} + .navigation a { color : #FFC000; } diff --git a/templates/pages/index.html b/templates/pages/index.html index 18988f9..0f295e7 100644 --- a/templates/pages/index.html +++ b/templates/pages/index.html @@ -1,5 +1,8 @@ {% extends "base.html" %} {% block content %} -{% include page %} +
    + {% include page %} +
    +
    {% endblock %} From 322a7fb204ac4c9d7b034a6a7d6e45eaf24706c6 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Fri, 9 Dec 2011 13:01:16 +0100 Subject: [PATCH 18/21] Show hacker emblem --- static/css/main.css | 4 +++ static/img/hacker.png | Bin 0 -> 399 bytes templates/base.html | 56 +++++++++++++++++++++++++----------------- 3 files changed, 37 insertions(+), 23 deletions(-) create mode 100644 static/img/hacker.png diff --git a/static/css/main.css b/static/css/main.css index 96869c0..17453e2 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -191,6 +191,10 @@ ul { padding-left : 5px; } +.emblems { + text-align: right; +} + .markdown h3 { margin: 1em 0; } diff --git a/static/img/hacker.png b/static/img/hacker.png new file mode 100644 index 0000000000000000000000000000000000000000..5a2e1850f017f2b23c8628ba65cb6a46c3cf19d0 GIT binary patch literal 399 zcmV;A0dW3_P)IWd0001HP)t-sW@cvp z|NrIX
    -
    -
    - -
    - {% block content %} - {% endblock %} -
    -
    +
    +
    + + + +
    + {% block content %} + {% endblock %} +
    +
    + + +
    From ee74f485af6e6c1821b990635921804d98fedb86 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Fri, 9 Dec 2011 16:59:24 +0100 Subject: [PATCH 19/21] Update layout --- static/css/main.css | 41 +++++++++++++++++++++++------------------ templates/base.html | 33 +++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/static/css/main.css b/static/css/main.css index 17453e2..cb37520 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -20,8 +20,7 @@ a:visited { body { background-color : #000000; color : #000000; - font-family : sans, sans-serif; - padding-left : 10px; + font-family : "DejaVu Sans", sans, sans-serif; } dd { @@ -42,7 +41,7 @@ ul { } #container { - margin : 20px auto; + margin : 0 auto 0 auto; width : 700px; } @@ -50,21 +49,14 @@ ul { background-color : #0C191C; color : #EEEEEC; font-size : 10px; - padding-left : 5px; -} - -#container #header { - border-top-left-radius : 30px; - border-top-right-radius : 30px; - -moz-border-radius-topleft : 30px; - -moz-border-radius-topright : 30px; + padding : 5px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; } #content { margin-left : 100px; - padding-bottom : 1px; - padding-left : 20px; - padding-right : 20px; + padding: 5px 20px 1px 20px; } #content .container { @@ -100,26 +92,37 @@ ul { background-color : #252A2B; } +#subheader { + background-color: #0c181b; + color: #fff; + text-align: right; + font-size: 12px; + padding: 5px; +} + #logo { float : left; height : 100px; - margin : -13px 20px 23px 5px; + margin : 0 20px 23px 0; width : 100px; } #ryu { color : #F57900; + position: relative; + top: -3px; } #slash { position: relative; - top: 5px; + top: 3px; } #menu { margin-left : -5px; float : left; width : 100px; + clear: left; } #menu a { @@ -129,8 +132,8 @@ ul { #title { color : #EEEEEC; - height : 100px; - line-height : 100px; + height : 50px; + line-height : 50px; } #title sup { @@ -193,6 +196,8 @@ ul { .emblems { text-align: right; + float: right; + margin-top: -2px; } .markdown h3 { diff --git a/templates/base.html b/templates/base.html index 6c451a8..9222fb2 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,16 +8,20 @@ {% block extrastyle %}{% endblock %} -
    - + +
    + This might just be my website. +
    + +
    -
    + From 1bd58d39d968f8eee13ef076a2a5c78f60eb92de Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Fri, 9 Dec 2011 17:02:41 +0100 Subject: [PATCH 20/21] Show django emblem --- static/img/django.gif | Bin 0 -> 962 bytes templates/base.html | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 static/img/django.gif diff --git a/static/img/django.gif b/static/img/django.gif new file mode 100644 index 0000000000000000000000000000000000000000..a0548a66d2800b1afa58bfbf80fd22da31477fbf GIT binary patch literal 962 zcmZ?wbhEHb3}E1AcqYkUo9Anu?rxLoW0&veP!M39?H%5j8rhQm`P-MdTbD*OrA0KS zId9vtdE1v|_m>~ObYlAY`2|yIawb$nwPbizM9$y7{L{D3t&97MrqxYZ zKlkj-i!MdMhb|s3o>8CLQ`EAk@Ai{>7w%k1>dIfSZ^PzeJ2U%Ax1ZX(=HTW-myU@AC%7WR0Qg->2LC#AcvW7(w6Ws_rCGTWC<^r?(?DGZ*pcJ{WDd*a)2 z7VcabQkPUYyCtbJKcly#fAx&C-r|t@q}q8MbG9s5zIUBtVW3r(*Zh~{|C7#NHzRhfn$xKQzPAm^4#5e>MZeI8AKH3%K6LF`* z@bSJtW~ZbJMGoF4CRlH|nvl@xXd=QRaYf+Lrl*|V8k>AAJ{EOu6V^E{Bk1|5;Uc3l zzkuniFE368GBAW(a8lH|x`OYR1w+EYNv&%X7R;D@t+a=gVcMoytPEza!?q;BD3J4drj#Z9Uc8Vy>O3Pko9ch=c-^Ja3S z^q3#G@9^W_qo3d98y@v;I@-vgHY0&uXvcK q9T((zJTom Willemsen
    + + django emblem + + hacker emblem From 60b436532e5857d3e1ff79a9ba64942085906d79 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Fri, 9 Dec 2011 17:10:44 +0100 Subject: [PATCH 21/21] Style/whitespace changes --- static/css/login.css | 2 +- static/css/main.css | 178 +++++++++++++++++++++---------------------- templates/base.html | 7 +- 3 files changed, 93 insertions(+), 94 deletions(-) diff --git a/static/css/login.css b/static/css/login.css index a9ab3ed..4b4dd1d 100644 --- a/static/css/login.css +++ b/static/css/login.css @@ -5,7 +5,7 @@ p.errornote { margin: 0; - color: #CC0000; + color: #CC0000; } .errorlist { diff --git a/static/css/main.css b/static/css/main.css index cb37520..8ca8ab3 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,26 +1,26 @@ * { - border : 0; - margin : 0; - padding : 0; + border: 0; + margin: 0; + padding: 0; } a { - color : #FFC000; - text-decoration : none; + color: #FFC000; + text-decoration: none; } a:hover { - text-decoration : underline; + text-decoration: underline; } a:visited { - color : #FF8A00; + color: #FF8A00; } body { - background-color : #000000; - color : #000000; - font-family : "DejaVu Sans", sans, sans-serif; + background-color: #000000; + color: #000000; + font-family: "DejaVu Sans", sans, sans-serif; } dd { @@ -28,175 +28,175 @@ dd { } p { - margin : 1em 0px; + margin: 1em 0px; } ul { - margin : 1em 0; - padding-left : 40px; + margin: 1em 0; + padding-left: 40px; } #body { - background-color : #777; + background-color: #777; } #container { - margin : 0 auto 0 auto; - width : 700px; + margin: 0 auto 0 auto; + width: 700px; } #container #footer { - background-color : #0C191C; - color : #EEEEEC; - font-size : 10px; - padding : 5px; - border-bottom-left-radius: 5px; + background-color: #0C191C; + color: #EEEEEC; + font-size: 10px; + padding: 5px; + border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } #content { - margin-left : 100px; - padding: 5px 20px 1px 20px; + margin-left: 100px; + padding: 5px 20px 1px 20px; } #content .container { - color : #EEEEEC; + color: #EEEEEC; } #content .container .header { - background-color : transparent; - padding-bottom : 5px; - padding-left : 0; - padding-top : 5px; + background-color: transparent; + padding-bottom: 5px; + padding-left: 0; + padding-top: 5px; } #content .container .header a { - color : inherit; - text-decoration : none; + color: inherit; + text-decoration: none; } #content .container .header span.tagline { - color: #EEEEEC; + color: #EEEEEC; font-size: 12px; } #content .container .header span.title { - background-color : #2E3436; - left : -5px; - padding : 5px; - position : relative; - top : -5px; + background-color: #2E3436; + left: -5px; + padding: 5px; + position: relative; + top: -5px; } #header { - background-color : #252A2B; + background-color: #252A2B; } #subheader { background-color: #0c181b; - color: #fff; - text-align: right; - font-size: 12px; - padding: 5px; + color: #fff; + text-align: right; + font-size: 12px; + padding: 5px; } #logo { - float : left; - height : 100px; - margin : 0 20px 23px 0; - width : 100px; + float: left; + height: 100px; + margin: 0 20px 23px 0; + width: 100px; } #ryu { - color : #F57900; + color: #F57900; position: relative; - top: -3px; + top: -3px; } #slash { - position: relative; - top: 3px; + position: relative; + top: 3px; } #menu { - margin-left : -5px; - float : left; - width : 100px; - clear: left; + margin-left: -5px; + float: left; + width: 100px; + clear: left; } #menu a { - color : #FFC000; - text-decoration : none; + color: #FFC000; + text-decoration: none; } #title { - color : #EEEEEC; - height : 50px; - line-height : 50px; + color: #EEEEEC; + height: 50px; + line-height: 50px; } #title sup { - font-size : 11px; - position : relative; - top : 5px; + font-size: 11px; + position: relative; + top: 5px; } .activity_even { - background-color : #2E3436; + background-color: #2E3436; } .activity_even, .activity_uneven { - border-bottom : 1px solid #444444; - color : #EEEEEC; - font-size : 12px; - margin: 0 20px; - padding : 2px 0 2px 5px; + border-bottom: 1px solid #444444; + color: #EEEEEC; + font-size: 12px; + margin: 0 20px; + padding: 2px 0 2px 5px; } .activity_last { - border-bottom : none; + border-bottom: none; } .activity_uneven { - background-color : #0C191C; + background-color: #0C191C; } .container { - background-color : #0C191C; - border : 1px solid #2E3436; - margin-bottom : 20px; - padding : 2px 5px; - padding-left : 10px; + background-color: #0C191C; + border: 1px solid #2E3436; + margin-bottom: 20px; + padding: 2px 5px; + padding-left: 10px; } .clear { - clear : both; + clear: both; } .clearleft { - clear : left; + clear: left; } .container .header { - background-color : #2E3436; - color : #F57900; - font-weight : bold; - margin : -2px -5px 0 -10px; - padding-left : 5px; + background-color: #2E3436; + color: #F57900; + font-weight: bold; + margin: -2px -5px 0 -10px; + padding-left: 5px; } .container .footer { - background-color : #2E3436; - color : #0C191C; - font-size : 10px; - margin : 0 -5px -2px -10px; - padding-left : 5px; + background-color: #2E3436; + color: #0C191C; + font-size: 10px; + margin: 0 -5px -2px -10px; + padding-left: 5px; } .emblems { text-align: right; - float: right; + float: right; margin-top: -2px; } @@ -205,9 +205,9 @@ ul { } .navigation a { - color : #FFC000; + color: #FFC000; } .navigation a.next { - float : right; + float: right; } diff --git a/templates/base.html b/templates/base.html index c90a588..c6d6c26 100644 --- a/templates/base.html +++ b/templates/base.html @@ -10,6 +10,7 @@