--- /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']
def listener_changed(sender, instance, **kwargs):
sender._object_cache = {}
+ def next(self):
+ Tag.objects.filter(ordering__gt=self.ordering)
+
models.signals.pre_save.connect(Tag.listener_changed, sender=Tag)
"""
File in repository.
"""
- creator = models.ForeignKey(User, null=True, blank=True, editable=False)
+ creator = models.ForeignKey(User, null=True, blank=True, editable=False,
+ related_name="created_documents")
head = models.ForeignKey(Change,
null=True, blank=True, default=None,
help_text=_("This document's current head."),
editable=False)
+ user = models.ForeignKey(User, null=True, blank=True)
+ stage = models.ForeignKey(Tag, null=True, blank=True)
+
def __unicode__(self):
return u"{0}, HEAD: {1}".format(self.id, self.head_id)
class Meta:
model = Book
- exclude = ['gallery']
+ exclude = ['gallery', 'parent', 'parent_number']
+ prepopulated_fields = {'slug': ['title']}
def clean(self):
super(DocumentCreateForm, self).clean()
chunk = Chunk.objects.get(book=self.instance.book, slug=slug)
except Chunk.DoesNotExist:
return slug
- if chunk == self:
+ if chunk == self.instance:
return slug
raise forms.ValidationError(_('Chunk with this slug already exists'))
grouper = None
return list(_generator(iterable))
+
+
+def active_tab(tab):
+ """
+ View decorator, which puts tab info on a request.
+ """
+ def wrapper(f):
+ @wraps(f)
+ def wrapped(request, *args, **kwargs):
+ request.wiki_active_tab = tab
+ return f(request, *args, **kwargs)
+ return wrapped
+ return wrapper
+
creator=creator, slug=slug, comment=comment)
return new_chunk
+ def list_html(self):
+ _list_html = render_to_string('wiki/chunk_list_item.html',
+ {'chunk': self})
+ return mark_safe(_list_html)
+
@staticmethod
def listener_saved(sender, instance, created, **kwargs):
if instance.book:
-{% extends "base.html" %}
{% load compressed i18n %}
+{% load wiki %}
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+ {% compressed_css 'listing' %}
+ <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}style.css" />
+ <title>{% block title %}{% trans "Platforma Redakcyjna" %}{% endblock title %}</title>
+</head>
+<body>
-{% block title %}{{ document_name }} - {{ block.super }}{% endblock %}
+<div id="tabs-nav">
-{% block extrahead %}
-{% compressed_css 'listing' %}
-{% endblock %}
+ <img id="logo" src="{{ STATIC_URL }}img/wl-orange.png" />
-{% block extrabody %}
-{% compressed_js 'listing' %}
-{% endblock %}
+ <div id="tabs-nav-left">
+ {% main_tabs %}
+ <!--a {% ifequal active_tab "user" %}class="active" {% endifequal %}href="{% url wiki_user %}">{% trans "User" %}</a>
+ <a {% ifequal active_tab "all" %}class="active" {% endifequal %}href="{% url wiki_document_list %}">{% trans "All" %}</a>
+ <a {% ifequal active_tab "create" %}class="active" {% endifequal %}href="{% url wiki_create_missing %}">{% trans "Add" %}</a>
+ <a {% ifequal active_tab "upload" %}class="active" {% endifequal %}href="{% url wiki_upload %}">{% trans "Upload" %}</a-->
+ </div>
+
+ <span id="login-box">
+ {% include "registration/head_login.html" %}
+ </span>
+
+ <div class='clr' ></div>
+</div>
+
+<div id="content">
-{% block maincontent %}
-<h1><img src="{{ STATIC_URL }}img/logo.png">{% trans "Platforma Redakcyjna" %}</h1>
<div id="wiki_layout_left_column">
{% block leftcolumn %}
{% endblock leftcolumn %}
{% block rightcolumn %}
{% endblock rightcolumn %}
</div>
-{% endblock maincontent %}
\ No newline at end of file
+
+</div>
+
+{% compressed_js 'listing' %}
+{% block extrabody %}
+{% endblock %}
+</body>
+</html>
</td>
<td><a href="{% url wiki_chunk_edit book.slug c.chunk.slug%}">[{% trans "edit" %}]</a></td>
<td>{% if c.chunk.publishable %}P{% endif %}</td>
+ <td>{% if c.chunk.user.is_authenticated %}
+ <a href="{% url wiki_user c.chunk.user.username %}">{{ c.chunk.user }}</a>
+ {% endif %}</td>
<td><a href="{% url wiki_chunk_add book.slug c.chunk.slug %}">[+]</a></td>
</tr>
{% endfor %}
--- /dev/null
+<tr>
+ <td colspan="3">
+ <a target="_blank"
+ href="{% url wiki_chunk_edit chunk.book.slug chunk.slug %}">[?]</a>
+ <a target="_blank"
+ href="{{ chunk.get_absolute_url }}">
+ {{ chunk.pretty_name }}</a>
+ </td>
+</tr>
{% extends "wiki/base.html" %}
{% load i18n %}
+{% load pagination_tags %}
{% block extrabody %}
{{ block.super }}
{% block leftcolumn %}
<form method="get" action="#">
- <table id="file-list">
+ <table id="file-list">
<thead>
<tr><th>Filtr:</th>
<th><input autocomplete="off" name="filter" id="file-list-filter" type="text" size="40" /></th>
</tr>
</thead>
<tbody>
+ {% autopaginate books 20 %}
{% for book in books %}
{{ book.list_html }}
{% endfor %}
</tbody>
+ <tr><td colspan="3">{% paginate %}</td></tr>
</table>
</form>
{% endblock leftcolumn %}
--- /dev/null
+{% for tab in tabs %}
+ <a {% ifequal active_tab tab.slug %}class="active" {% endifequal %}href="{{ tab.url }}">{{ tab.caption }}</a>
+{% endfor %}
from __future__ import absolute_import
+from django.core.urlresolvers import reverse
from django.template.defaultfilters import stringfilter
from django import template
+from django.utils.translation import ugettext as _
+
register = template.Library()
-from wiki.models import split_name
-@register.filter
-@stringfilter
-def wiki_title(value):
- parts = (p.replace('_', ' ').title() for p in split_name(value))
- return ' / '.join(parts)
+class Tab(object):
+ slug = None
+ caption = None
+ url = None
+
+ def __init__(self, slug, caption, url):
+ self.slug = slug
+ self.caption = caption
+ self.url = url
+
+
+@register.inclusion_tag("wiki/main_tabs.html", takes_context=True)
+def main_tabs(context):
+ active = getattr(context['request'], 'wiki_active_tab', None)
+
+ tabs = []
+ user = context['user']
+ if user.is_authenticated():
+ tabs.append(Tab('my', _('Assigned to me'), reverse("wiki_user")))
+
+ tabs.append(Tab('unassigned', _('Unassigned'), reverse("wiki_unassigned")))
+ tabs.append(Tab('all', _('All'), reverse("wiki_document_list")))
+ tabs.append(Tab('create', _('Add'), reverse("wiki_create_missing")))
+ tabs.append(Tab('upload', _('Upload'), reverse("wiki_upload")))
+
+ if user.is_staff:
+ tabs.append(Tab('admin', _('Admin'), reverse("admin:index")))
+
+ return {"tabs": tabs, "active_tab": active}
#url(r'^catalogue/([^/]+)/$', 'document_list'),
#url(r'^catalogue/([^/]+)/([^/]+)/$', 'document_list'),
#url(r'^catalogue/([^/]+)/([^/]+)/([^/]+)$', 'document_list'),
+ url(r'^unassigned/$', 'unassigned', name='wiki_unassigned'),
+ url(r'^user/$', 'my', name='wiki_user'),
+ url(r'^user/(?P<username>[^/]+)/$', 'user', name='wiki_user'),
url(r'^edit/(?P<slug>[^/]+)/(?:(?P<chunk>[^/]+)/)?$',
'editor', name="wiki_editor"),
url(r'^create/(?P<slug>[^/]*)/',
'create_missing', name='wiki_create_missing'),
+ url(r'^create/',
+ 'create_missing', name='wiki_create_missing'),
url(r'^gallery/(?P<directory>[^/]+)/$',
'gallery', name="wiki_gallery"),
from django.conf import settings
+from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
from django.views.decorators.http import require_POST, require_GET
from django.core.urlresolvers import reverse
from wiki.helpers import (JSONResponse, JSONFormInvalid, JSONServerError,
- ajax_require_permission, recursive_groupby)
+ ajax_require_permission, recursive_groupby, active_tab)
from django import http
from django.shortcuts import get_object_or_404, redirect
from django.http import Http404
MAX_LAST_DOCS = 10
+@active_tab('all')
@never_cache
def document_list(request):
return direct_to_template(request, 'wiki/document_list.html', extra_context={
})
+@active_tab('unassigned')
+@never_cache
+def unassigned(request):
+ return direct_to_template(request, 'wiki/document_list.html', extra_context={
+ 'books': Chunk.objects.filter(user=None),
+ 'last_books': sorted(request.session.get("wiki_last_books", {}).items(),
+ key=lambda x: x[1]['time'], reverse=True),
+ })
+
+
+@never_cache
+def user(request, username=None):
+ if username is None:
+ if request.user.is_authenticated():
+ user = request.user
+ else:
+ raise Http404
+ else:
+ user = get_object_or_404(User, username=username)
+
+ return direct_to_template(request, 'wiki/document_list.html', extra_context={
+ 'books': Chunk.objects.filter(user=user),
+ 'last_books': sorted(request.session.get("wiki_last_books", {}).items(),
+ key=lambda x: x[1]['time'], reverse=True),
+ })
+my = login_required(active_tab('my')(user))
+
+
@never_cache
def editor(request, slug, chunk=None, template_name='wiki/document_details.html'):
try:
})
-def create_missing(request, slug):
+@active_tab('create')
+def create_missing(request, slug=None):
+ if slug is None:
+ slug = ''
slug = slug.replace(' ', '-')
if request.method == "POST":
})
+@active_tab('upload')
def upload(request):
if request.method == "POST":
form = forms.DocumentsUploadForm(request.POST, request.FILES)
'django_cas.middleware.CASMiddleware',
'django.middleware.doc.XViewMiddleware',
+ 'pagination.middleware.PaginationMiddleware',
'maintenancemode.middleware.MaintenanceModeMiddleware',
)
'south',
'sorl.thumbnail',
'filebrowser',
+ 'pagination',
'dvcs',
'wiki',
*/
body {
- background-color: #84BF2A;
+ margin: 0;
+ font-family: verdana, sans-serif;
+ font-size: 12px;
}
-#content {
- background: #EFEFEF;
- border: 1px solid black;
- padding: 0.5em 2em;
- margin: 1em;
- overflow: hidden;
+
+.clr {
+ clear: both;
+}
+
+#tabs-nav {
+ padding: 5px 5px 0 10px;
+ background: #ffdfbf;
+ border-bottom: 1px solid #ff8000;
+ position: relative;
+}
+
+#tabs-nav-left {
+ margin-left: 60px;
+}
+
+#tabs-nav-left a {
+ display: block;
+ float: left;
+ padding: 5px 20px 5px 20px;
+ margin-bottom: -1px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: rgba(0,0,0,0);
}
-#content h1 img {
- vertical-align: middle;
+#tabs-nav-left .active {
+ background: white;
+ border-color: #ff8000 #ff8000 white #ff8000;
}
-#content h1 {
- border-bottom: 2px solid black;
- padding: 0.5em;
- font-size: 2opt;
- font-family: sans-serif;
+#login-box {
+ float: right;
}
+#logo {
+ position: absolute;
+ bottom: 0;
+}
+
+#content {
+ padding: 10px;
+}
+
+
+
#file-list {
overflow: visible;
float: left;
}
a, a:visited, a:active {
- color: blue;
+ color: #bf6000;
text-decoration: none;
}
}
-#loading-overlay {
- display: none;
-}
.error {
color: red;
Django>=1.1.1,<1.2
sorl-thumbnail>=3.2
django-maintenancemode>=0.9
+django-pagination
# migrations
south>=0.6