-from django.contrib.admin import site
-from dvcs.models import Document, Change, Tag
+from django.contrib import admin
 
-site.register(Tag)
-site.register(Document)
-site.register(Change)
+from dvcs import models
+
+
+class TagAdmin(admin.ModelAdmin):
+    list_display = ['name', 'slug', 'ordering']
+
+admin.site.register(models.Tag, TagAdmin)
+admin.site.register(models.Document)
+admin.site.register(models.Change)
 
 from south.v2 import SchemaMigration
 from django.db import models
 
-
 class Migration(SchemaMigration):
 
     def forwards(self, orm):
         db.create_table('dvcs_change', (
             ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
             ('author', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
-            ('author_desc', self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True)),
+            ('author_name', self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True)),
+            ('author_email', self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True)),
             ('patch', self.gf('django.db.models.fields.TextField')(blank=True)),
             ('tree', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dvcs.Document'])),
             ('revision', self.gf('django.db.models.fields.IntegerField')(db_index=True)),
         # Adding model 'Document'
         db.create_table('dvcs_document', (
             ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('creator', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
+            ('creator', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='created_documents', null=True, to=orm['auth.User'])),
             ('head', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['dvcs.Change'], null=True, blank=True)),
+            ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)),
+            ('stage', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dvcs.Tag'], null=True, blank=True)),
         ))
         db.send_create_signal('dvcs', ['Document'])
 
             'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
         },
         'auth.permission': {
-            'Meta': {'ordering': "('content_type__app_label', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': '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'}),
         'dvcs.change': {
             'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'Change'},
             'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
-            'author_desc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'author_email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'author_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
             'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
             'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
             'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
         },
         'dvcs.document': {
             'Meta': {'object_name': 'Document'},
-            'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'created_documents'", 'null': 'True', 'to': "orm['auth.User']"}),
             'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dvcs.Change']", 'null': 'True', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'stage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Tag']", 'null': 'True', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
         },
         'dvcs.tag': {
             'Meta': {'ordering': "['ordering']", 'object_name': 'Tag'},
 
+++ /dev/null
-# 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 'Document.user'
-        db.add_column('dvcs_document', 'user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True), keep_default=False)
-
-        # Adding field 'Document.stage'
-        db.add_column('dvcs_document', 'stage', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['dvcs.Tag'], null=True), keep_default=False)
-
-
-    def backwards(self, orm):
-        
-        # Deleting field 'Document.user'
-        db.delete_column('dvcs_document', 'user_id')
-
-        # Deleting field 'Document.stage'
-        db.delete_column('dvcs_document', 'stage_id')
-
-
-    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', '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'})
-        },
-        'dvcs.change': {
-            'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'Change'},
-            'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
-            'author_desc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
-            'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
-            'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'merge_parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'merge_children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
-            'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['dvcs.Change']"}),
-            'patch': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
-            'publishable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
-            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['dvcs.Tag']", 'symmetrical': 'False'}),
-            'tree': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Document']"})
-        },
-        'dvcs.document': {
-            'Meta': {'object_name': 'Document'},
-            'creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'created_documents'", 'null': 'True', 'to': "orm['auth.User']"}),
-            'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['dvcs.Change']", 'null': 'True', 'blank': 'True'}),
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'stage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['dvcs.Tag']", 'null': 'True'}),
-            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
-        },
-        'dvcs.tag': {
-            'Meta': {'ordering': "['ordering']", 'object_name': 'Tag'},
-            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
-            'ordering': ('django.db.models.fields.IntegerField', [], {}),
-            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'})
-        }
-    }
-
-    complete_apps = ['dvcs']
 
         Data contains a pickled diff needed to reproduce the initial document.
     """
     author = models.ForeignKey(User, null=True, blank=True)
-    author_desc = models.CharField(max_length=128, null=True, blank=True)
+    author_name = models.CharField(max_length=128, null=True, blank=True)
+    author_email = models.CharField(max_length=128, null=True, blank=True)
     patch = models.TextField(blank=True)
     tree = models.ForeignKey('Document')
     revision = models.IntegerField(db_index=True)
                 self.author.last_name, 
                 self.author.email)
         else:
-            return self.author_desc
+            return "%s <%s>" % (
+                self.author_name,
+                self.author_email
+                )
 
 
     def save(self, *args, **kwargs):
         return text
 
     def make_child(self, patch, description, author=None,
-            author_desc=None, tags=None):
+            author_name=None, author_email=None, tags=None):
         ch = self.children.create(patch=patch,
                         tree=self.tree, author=author,
-                        author_desc=author_desc,
+                        author_name=author_name,
+                        author_email=author_email,
                         description=description)
         if tags is not None:
             ch.tags = tags
         return ch
 
     def make_merge_child(self, patch, description, author=None, 
-            author_desc=None, tags=None):
+            author_name=None, author_email=None, tags=None):
         ch = self.merge_children.create(patch=patch,
                         tree=self.tree, author=author,
-                        author_desc=author_desc,
+                        author_name=author_name,
+                        author_email=author_email,
                         description=description,
                         tags=tags)
         if tags is not None:
     def apply_to(self, text):
         return mdiff.patch(text, pickle.loads(self.patch.encode('ascii')))
 
-    def merge_with(self, other, author=None, author_desc=None,
+    def merge_with(self, other, author=None, 
+            author_name=None, author_email=None, 
             description=u"Automatic merge."):
         assert self.tree_id == other.tree_id  # same tree
         if other.parent_id == self.pk:
         patch = self.make_patch(local, result)
         return self.children.create(
                     patch=patch, merge_parent=other, tree=self.tree,
-                    author=author, author_desc=author_desc,
+                    author=author,
+                    author_name=author_name,
+                    author_email=author_email,
                     description=description)
 
     def revert(self, **kwargs):
             patch = kwargs['patch']
 
         author = kwargs.get('author', None)
-        author_desc = kwargs.get('author_desc', None)
+        author_name = kwargs.get('author_name', None)
+        author_email = kwargs.get('author_email', None)
         tags = kwargs.get('tags', [])
         if tags:
             # set stage to next tag after the commited one
         old_head = self.head
         if parent != old_head:
             change = parent.make_merge_child(patch, author=author, 
-                    author_desc=author_desc,
+                    author_name=author_name,
+                    author_email=author_email,
                     description=kwargs.get('description', ''),
                     tags=tags)
             # not Fast-Forward - perform a merge
             self.head = old_head.merge_with(change, author=author,
-                    author_desc=author_desc)
+                    author_name=author_name,
+                    author_email=author_email)
         else:
             self.head = parent.make_child(patch, author=author, 
-                    author_desc=author_desc, 
+                    author_name=author_name,
+                    author_email=author_email,
                     description=kwargs.get('description', ''),
                     tags=tags)
 
 
 
 META_REGEX = re.compile(r'\s*<!--\s(.*?)-->', re.DOTALL | re.MULTILINE)
 STAGE_TAGS_RE = re.compile(r'^#stage-finished: (.*)$', re.MULTILINE)
+AUTHOR_RE = re.compile(r'\s*(.*?)\s*<(.*)>\s*')
 
 
 def urlunquote(url):
     chunk = orm.Chunk.objects.create(
         book=book,
         number=1,
-        slug='1',
-        comment='cz. 1')
+        slug='1')
     head = orm['dvcs.Change'].objects.create(
         tree=chunk,
         revision=-1,
 
         description = STAGE_TAGS_RE.sub('', description)
 
+        author = author_name = author_email = None
+        author_desc = fctx.user().decode("utf-8", 'replace')
+        m = AUTHOR_RE.match(author_desc)
+        if m:
+            try:
+                author = orm['auth.User'].objects.get(username=m.group(1), email=m.group(2))
+            except orm['auth.User'].DoesNotExist:
+                author_name = m.group(1)
+                author_email = m.group(2)
+        else:
+            author_name = author_desc
+
         head = orm['dvcs.Change'].objects.create(
             tree=chunk,
             revision=rev + 1,
             patch=make_patch(old_data, data),
             created_at=datetime.datetime.fromtimestamp(fctx.date()[0]),
             description=description,
-            author_desc=fctx.user().decode("utf-8", 'replace'),
+            author=author,
+            author_name=author_name,
+            author_email=author_email,
             parent=chunk.head
             )
         head.tags = tags
         'dvcs.change': {
             'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'Change'},
             'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
-            'author_desc': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'author_email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'author_name': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
             'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'db_index': 'True'}),
             'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}),
             'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
 
     book = models.ForeignKey(Book, editable=False)
     number = models.IntegerField()
     slug = models.SlugField()
-    comment = models.CharField(max_length=255)
+    comment = models.CharField(max_length=255, blank=True)
 
     class Meta:
         unique_together = [['book', 'number'], ['book', 'slug']]
             return cls.objects.get(book__slug=slug, slug=chunk)
 
     def pretty_name(self):
-        return "%s, %s (%d/%d)" % (self.book.title, self.comment, 
-                self.number, len(self.book))
+        title = self.book.title
+        if self.comment:
+            title += ", %s" % self.comment
+        count = len(self.book)
+        if count > 1:
+            title += " (%d/%d)" % (self.number, len(self.book))
+        return title
 
     def split(self, slug, comment='', creator=None):
         """ Create an empty chunk after this one """
 
 {% extends "wiki/base.html" %}
-{% load i18n %}
+{% load comments i18n %}
 
 {% block leftcolumn %}
 
 {% endblock leftcolumn %}
 
 {% block rightcolumn %}
-
+{% render_comment_list for book %}
+{% render_comment_form for book %}
 
 {% endblock rightcolumn %}
 
 
 {% block leftcolumn %}
        <form enctype="multipart/form-data" method="POST" action="">
+    {% csrf_token %}
        {{ form.as_p }}
 
        <p><button type="submit">{% trans "Create document" %}</button></p>
 {% endblock leftcolumn %}
 
 {% block rightcolumn %}
-{% endblock rightcolumn %}
\ No newline at end of file
+{% endblock rightcolumn %}
 
 
        <span data-key="gallery">{{ chunk.book.gallery }}</span>
        <span data-key="revision">{{ revision }}</span>
+    <span data-key="diff">{{ request.GET.diff }}</span>
 
        {% block meta-extra %} {% endblock %}
 </div>
 
                        {% endfor %}
                </ol>
        </div>
+
+    <h2>{% trans "Recent activity" %}</h2>
+    {% wall %}
 {% endblock rightcolumn %}
 
 </p>
 
 <form enctype="multipart/form-data" method="POST" action="">
+{% csrf_token %}
 {{ form.as_p }}
 <p><button type="submit">{% trans "Upload" %}</button></p>
 </form>
 
--- /dev/null
+{% load i18n %}
+{% load gravatar %}
+
+<ul class='wall' style='padding-left: 0; list-style: none;'>
+{% for item in wall %}
+    <li style='clear: left; border-top: 1px dotted gray;  padding-bottom:1em; margin-bottom: 1em;'>
+        <div style='float: left;margin-right: 1em;'>
+            {% if item.get_email %}
+                {% gravatar_img_for_email item.get_email 32 %}
+                <br/>
+            {% endif %}
+
+            <img src='{{ STATIC_URL }}img/wall/{{ item.tag}}.png' alt='{% trans item.tag %}' />
+        </div>
+
+        {{ item.timestamp }}
+        <br/>
+        {% if item.user %}
+            <a href="{% url wiki_user item.user.username %}">
+            {{ item.user.first_name }} {{ item.user.last_name }}</a>
+            <{{ item.user.email }}>
+        {% else %}
+            {{ item.user_name }}
+            {% if item.get_email %}
+                <{{ item.get_email }}>
+            {% endif %}
+        {% endif %}
+        <br/><a target="_blank" href='{{ item.url }}'>{{ item.title }}</a>
+        <br/>{{ item.summary }}
+        </li>
+{% endfor %}
+</ul>
 
 from __future__ import absolute_import
 
 from django.core.urlresolvers import reverse
+from django.contrib.comments.models import Comment
 from django.template.defaultfilters import stringfilter
 from django import template
 from django.utils.translation import ugettext as _
 
+from wiki.models import Book
+from dvcs.models import Change
 
 register = template.Library()
 
         tabs.append(Tab('admin', _('Admin'), reverse("admin:index")))
 
     return {"tabs": tabs, "active_tab": active}
+
+
+class WallItem(object):
+    title = ''
+    summary = ''
+    url = ''
+    timestamp = ''
+    user = None
+    email = ''
+
+    def __init__(self, tag):
+        self.tag = tag
+
+    def get_email(self):
+        if self.user:
+            return self.user.email
+        else:
+            return self.email
+
+
+def changes_wall(max_len):
+    qs = Change.objects.filter(revision__gt=-1).order_by('-created_at').select_related()
+    qs = qs[:max_len]
+    for item in qs:
+        tag = 'stage' if item.tags.count() else 'change'
+        chunk = item.tree.chunk
+        w  = WallItem(tag)
+        w.title = chunk.pretty_name()
+        w.summary = item.description
+        w.url = reverse('wiki_editor', 
+                args=[chunk.book.slug, chunk.slug]) + '?diff=%d' % item.revision
+        w.timestamp = item.created_at
+        w.user = item.author
+        w.email = item.author_email
+        yield w
+
+
+def published_wall(max_len):
+    qs = Book.objects.exclude(last_published=None).order_by('-last_published')
+    qs = qs[:max_len]
+    for item in qs:
+        w  = WallItem('publish')
+        w.title = item.title
+        w.summary = item.title
+        w.url = chunk.book.get_absolute_url()
+        w.timestamp = item.last_published
+        w.user = item.last_published_by
+        yield w
+
+
+def comments_wall(max_len):
+    qs = Comment.objects.filter(is_public=True).select_related().order_by('-submit_date')
+    qs = qs[:max_len]
+    for item in qs:
+        w  = WallItem('comment')
+        w.title = item.content_object
+        w.summary = item.comment
+        w.url = item.content_object.get_absolute_url()
+        w.timestamp = item.submit_date
+        w.user = item.user
+        w.email = item.user_email
+        yield w
+
+
+def big_wall(max_len, *args):
+    """
+        Takes some WallItem iterators and zips them into one big wall.
+        Input iterators must already be sorted by timestamp.
+    """
+    subwalls = []
+    for w in args:
+        try:
+            subwalls.append([next(w), w])
+        except StopIteration:
+            pass
+
+    while max_len and subwalls:
+        i, next_item = max(enumerate(subwalls), key=lambda x: x[1][0].timestamp)
+        yield next_item[0]
+        max_len -= 1
+        try:
+            next_item[0] = next(next_item[1])
+        except StopIteration:
+            del subwalls[i]
+
+
+@register.inclusion_tag("wiki/wall.html", takes_context=True)
+def wall(context, max_len=10):
+    return {
+        "request": context['request'],
+        "STATIC_URL": context['STATIC_URL'],
+        "wall": big_wall(max_len,
+            changes_wall(max_len),
+            published_wall(max_len),
+            comments_wall(max_len),
+        )}
 
 from __future__ import absolute_import
+from os import path
 from redakcja.settings.common import *
 
-DATABASE_ENGINE = 'sqlite3'    # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
-DATABASE_NAME = PROJECT_ROOT + '/dev.sqlite'             # Or path to database file if using sqlite3.
-DATABASE_USER = ''             # Not used with sqlite3.
-DATABASE_PASSWORD = ''         # Not used with sqlite3.
-DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
-DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+        'NAME': path.join(PROJECT_ROOT, 'dev.sqlite'), # 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.
+    }
+}
 
 try:
     LOGGING_CONFIG_FILE
 
 # If you set this to False, Django will make some optimizations so as not
 # to load the internationalization machinery.
 USE_I18N = True
+USE_L10N = True
+
 
 # Absolute path to the directory that holds media.
 # Example: "/home/media/media.lawrence.com/"
     "django.core.context_processors.debug",
     "django.core.context_processors.i18n",
     "redakcja.context_processors.settings", # this is instead of media
+    'django.core.context_processors.csrf',
     "django.core.context_processors.request",
 )
 
 
 MIDDLEWARE_CLASSES = (
     'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
 
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.sites',
     'django.contrib.admin',
     'django.contrib.admindocs',
+    'django.contrib.comments',
 
     'django_cas',
     'compress',
     'sorl.thumbnail',
     'filebrowser',
     'pagination',
+    'gravatar',
 
     'dvcs',
     'wiki',
 
 
 
 
-#file-list {
+#wiki_layout_left_column {
        overflow: visible;
        float: left;
        /*max-width: 50%;*/
 
 }
 
-#last-edited-list {
+#wiki_layout_right_column {
        float: left;
        max-width: 35%;
        margin-left: 5%;
 
 
                options.callback = function() {
                        var self = this;
+            if (CurrentDocument.diff) {
+                rev_from = CurrentDocument.diff[0];
+                rev_to = CurrentDocument.diff[1];
+                this.doc.fetchDiff({
+                    from: rev_from,
+                    to: rev_to,
+                    success: function(doc, data){
+                        var result = $.wiki.newTab(doc, ''+rev_from +' -> ' + rev_to, 'DiffPerspective');
+
+                        $(result.view).html(data);
+                        $.wiki.switchToTab(result.tab);
+                    }
+                });
+            }
 
                        // first time page is rendered
                $('#make-diff-button').click(function() {
 
                this.readonly = !!$("*[data-key='readonly']", meta).text();
 
                this.galleryLink = $("*[data-key='gallery']", meta).text();
+
+        var diff = $("*[data-key='diff']", meta).text();
+        diff = diff.split(',');
+        if (diff.length == 2 && diff[0] < diff[1])
+            this.diff = diff;
+        else if (diff.length == 1) {
+            diff = parseInt(diff);
+            if (diff != NaN)
+                this.diff = [diff - 1, diff];
+        }
+
                this.galleryImages = [];
                this.text = null;
                this.has_local_changes = false;
 
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     (r'^admin/', include(admin.site.urls)),
 
+    (r'^comments/', include('django.contrib.comments.urls')),
+
     url(r'^$', 'django.views.generic.simple.redirect_to', {'url': '/documents/'}),
     url(r'^documents/', include('wiki.urls')),
     url(r'^storage/', include('dvcs.urls')),
 
 # git+git://github.com/fnp/librarian.git@master#egg=librarian
 
 ## Django
-Django>=1.1.1,<1.2
+Django>=1.3,<1.4
 sorl-thumbnail>=3.2
 django-maintenancemode>=0.9
 django-pagination
+django-gravatar
 
 # migrations
 south>=0.6