--- /dev/null
+[
+ {
+ "pk": 1,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 1,
+ "name": "Autokorekta",
+ "slug": "first_correction"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 2,
+ "name": "Tagowanie",
+ "slug": "tagging"
+ }
+ },
+ {
+ "pk": 3,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 3,
+ "name": "Korekta",
+ "slug": "proofreading"
+ }
+ },
+ {
+ "pk": 4,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 4,
+ "name": "Sprawdzenie przypis\u00f3w \u017ar\u00f3d\u0142a",
+ "slug": "annotation-proofreading"
+ }
+ },
+ {
+ "pk": 5,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 5,
+ "name": "Uwsp\u00f3\u0142cze\u015bnienie",
+ "slug": "modernisation"
+ }
+ },
+ {
+ "pk": 6,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 6,
+ "name": "Przypisy",
+ "slug": "annotations"
+ }
+ },
+ {
+ "pk": 7,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 7,
+ "name": "Motywy",
+ "slug": "themes"
+ }
+ },
+ {
+ "pk": 8,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 8,
+ "name": "Ostateczna redakcja literacka",
+ "slug": "editor-proofreading"
+ }
+ },
+ {
+ "pk": 9,
+ "model": "dvcs.tag",
+ "fields": {
+ "ordering": 9,
+ "name": "Ostateczna redakcja techniczna",
+ "slug": "technical-editor-proofreading"
+ }
+ }
+]
from south.v2 import SchemaMigration
from django.db import models
+
class Migration(SchemaMigration):
def forwards(self, orm):
))
db.send_create_signal('dvcs', ['Document'])
+ if not db.dry_run:
+ from django.core.management import call_command
+ call_command("loaddata", "stages.json")
+
def backwards(self, orm):
sender._object_cache = {}
def next(self):
- Tag.objects.filter(ordering__gt=self.ordering)
+ """
+ Returns the next tag - stage to work on.
+ Returns None for the last stage.
+ """
+ try:
+ return Tag.objects.filter(ordering__gt=self.ordering)[0]
+ except IndexError:
+ return None
models.signals.pre_save.connect(Tag.listener_changed, sender=Tag)
author = kwargs.get('author', None)
author_desc = kwargs.get('author_desc', None)
tags = kwargs.get('tags', [])
+ if tags:
+ # set stage to next tag after the commited one
+ self.stage = max(tags, key=lambda t: t.ordering).next()
old_head = self.head
if parent != old_head:
# This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from django.contrib.auth.models import User
+from django.db.models import Count
from django import forms
-from wiki.models import Book, Chunk
from django.utils.translation import ugettext_lazy as _
from dvcs.models import Tag
from wiki.constants import MASTERS
+from wiki.models import Book, Chunk
class DocumentTagForm(forms.Form):
"""
"""
Form used for editing a chunk.
"""
+ user = forms.ModelChoiceField(queryset=
+ User.objects.annotate(count=Count('document')).
+ order_by('-count', 'last_name', 'first_name'))
+
class Meta:
model = Chunk
return wrapped
return wrapper
+
+class BookChunks(object):
+ """
+ Yields the chunks of a book.
+ """
+
+ def __init__(self, book):
+ self.book = book
+
+ @property
+ def chunks(self):
+ return self.book.chunk_set.all()
+
+
+class ChoiceChunks(BookChunks):
+ """
+ Associates the given chunks iterable for a book.
+ """
+
+ chunks = None
+
+ def __init__(self, book, chunks):
+ self.book = book
+ self.chunks = chunks
+
msgstr ""
"Project-Id-Version: Platforma Redakcyjna\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-11-30 15:00+0100\n"
-"PO-Revision-Date: 2010-11-30 15:00+0100\n"
+"POT-Creation-Date: 2011-06-21 13:41+0200\n"
+"PO-Revision-Date: 2011-06-21 13:46+0100\n"
"Last-Translator: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>\n"
"Language-Team: Fundacja Nowoczesna Polska <fundacja@nowoczesnapolska.org.pl>\n"
"Language: \n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: constants.py:6
-msgid "First correction"
-msgstr "Autokorekta"
-
-#: constants.py:7
-msgid "Tagging"
-msgstr "Tagowanie"
-
-#: constants.py:8
-msgid "Initial Proofreading"
-msgstr "Korekta"
-
-#: constants.py:9
-msgid "Annotation Proofreading"
-msgstr "Sprawdzenie przypisów źródła"
-
-#: constants.py:10
-msgid "Modernisation"
-msgstr "Uwspółcześnienie"
-
-#: constants.py:11
-#: templates/wiki/tabs/annotations_view_item.html:3
-msgid "Annotations"
-msgstr "Przypisy"
-
-#: constants.py:12
-msgid "Themes"
-msgstr "Motywy"
-
-#: constants.py:13
-msgid "Editor's Proofreading"
-msgstr "Ostateczna redakcja literacka"
-
-#: constants.py:14
-msgid "Technical Editor's Proofreading"
-msgstr "Ostateczna redakcja techniczna"
-
-#: constants.py:18
-msgid "Ready to publish"
+#: forms.py:32
+msgid "Publishable"
msgstr "Gotowe do publikacji"
-#: forms.py:49
+#: forms.py:68
msgid "ZIP file"
msgstr "Plik ZIP"
-#: forms.py:82
+#: forms.py:99
+#: forms.py:137
msgid "Author"
msgstr "Autor"
-#: forms.py:83
+#: forms.py:100
+#: forms.py:138
msgid "Your name"
msgstr "Imię i nazwisko"
-#: forms.py:88
+#: forms.py:105
+#: forms.py:143
msgid "Author's email"
msgstr "E-mail autora"
-#: forms.py:89
+#: forms.py:106
+#: forms.py:144
msgid "Your email address, so we can show a gravatar :)"
msgstr "Adres e-mail, żebyśmy mogli pokazać gravatar :)"
-#: forms.py:95
+#: forms.py:112
+#: forms.py:150
msgid "Your comments"
msgstr "Twój komentarz"
-#: forms.py:96
+#: forms.py:113
msgid "Describe changes you made."
msgstr "Opisz swoje zmiany"
-#: forms.py:102
+#: forms.py:119
msgid "Completed"
msgstr "Ukończono"
-#: forms.py:103
+#: forms.py:120
msgid "If you completed a life cycle stage, select it."
msgstr "Jeśli został ukończony etap prac, wskaż go."
-#: models.py:94
-#, python-format
-msgid "Finished stage: %s"
-msgstr "Ukończony etap: %s"
+#: forms.py:151
+msgid "Describe the reason for reverting."
+msgstr "Opisz powód przywrócenia."
+
+#: forms.py:176
+#: forms.py:190
+msgid "Chunk with this slug already exists"
+msgstr "Część z tym slugiem już istnieje"
+
+#: forms.py:202
+msgid "Append to"
+msgstr "Dołącz do"
+
+#: models.py:25
+msgid "title"
+msgstr "tytuł"
+
+#: models.py:26
+msgid "slug"
+msgstr ""
+
+#: models.py:27
+msgid "scan gallery name"
+msgstr "nazwa galerii skanów"
+
+#: models.py:29
+msgid "parent"
+msgstr "rodzic"
+
+#: models.py:30
+msgid "parent number"
+msgstr "numeracja rodzica"
+
+#: models.py:40
+msgid "book"
+msgstr "książka"
+
+#: models.py:41
+msgid "books"
+msgstr "książki"
-#: models.py:153
+#: models.py:206
msgid "name"
msgstr "nazwa"
-#: models.py:157
+#: models.py:210
msgid "theme"
msgstr "motyw"
-#: models.py:158
+#: models.py:211
msgid "themes"
msgstr "motywy"
-#: views.py:167
+#: views.py:241
#, python-format
-msgid "Title already used for %s"
-msgstr "Nazwa taka sama jak dla pliku %s"
+msgid "Slug already used for %s"
+msgstr "Slug taki sam jak dla pliku %s"
-#: views.py:169
-msgid "Title already used in repository."
-msgstr "Plik o tej nazwie już istnieje w repozytorium."
+#: views.py:243
+msgid "Slug already used in repository."
+msgstr "Dokument o tym slugu już istnieje w repozytorium."
-#: views.py:175
+#: views.py:249
msgid "File should be UTF-8 encoded."
msgstr "Plik powinien mieć kodowanie UTF-8."
-#: views.py:358
+#: views.py:655
msgid "Tag added"
msgstr "Dodano tag"
-#: templates/wiki/base.html:15
+#: views.py:677
+msgid "Revision marked"
+msgstr "Wersja oznaczona"
+
+#: views.py:679
+msgid "Nothing changed"
+msgstr "Nic nie uległo zmianie"
+
+#: templates/wiki/base.html:9
msgid "Platforma Redakcyjna"
msgstr ""
+#: templates/wiki/book_append_to.html:8
+msgid "Append book"
+msgstr "Dołącz książkę"
+
+#: templates/wiki/book_detail.html:6
+#: templates/wiki/book_detail.html.py:46
+msgid "edit"
+msgstr "edytuj"
+
+#: templates/wiki/book_detail.html:16
+msgid "add basic document structure"
+msgstr "dodaj podstawową strukturę dokumentu"
+
+#: templates/wiki/book_detail.html:20
+msgid "change master tag to"
+msgstr "zmień tak master na"
+
+#: templates/wiki/book_detail.html:24
+msgid "add begin trimming tag"
+msgstr "dodaj początkowy ogranicznik"
+
+#: templates/wiki/book_detail.html:28
+msgid "add end trimming tag"
+msgstr "dodaj końcowy ogranicznik"
+
+#: templates/wiki/book_detail.html:34
+msgid "unstructured text"
+msgstr "tekst bez struktury"
+
+#: templates/wiki/book_detail.html:38
+msgid "unknown XML"
+msgstr "nieznany XML"
+
+#: templates/wiki/book_detail.html:42
+msgid "broken document"
+msgstr "uszkodzony dokument"
+
+#: templates/wiki/book_detail.html:60
+msgid "Apply fixes"
+msgstr "Wykonaj zmiany"
+
+#: templates/wiki/book_detail.html:66
+msgid "Append to other book"
+msgstr "Dołącz do innej książki"
+
+#: templates/wiki/book_detail.html:68
+msgid "Last published"
+msgstr "Ostatnio opublikowano"
+
+#: templates/wiki/book_detail.html:72
+msgid "Full XML"
+msgstr "Pełny XML"
+
+#: templates/wiki/book_detail.html:73
+msgid "HTML version"
+msgstr "Wersja HTML"
+
+#: templates/wiki/book_detail.html:74
+msgid "TXT version"
+msgstr "Wersja TXT"
+
+#: templates/wiki/book_detail.html:76
+msgid "EPUB version"
+msgstr "Wersja EPUB"
+
+#: templates/wiki/book_detail.html:77
+msgid "PDF version"
+msgstr "Wersja PDF"
+
+#: templates/wiki/book_detail.html:90
+#: templates/wiki/tabs/summary_view.html:30
+msgid "Publish"
+msgstr "Opublikuj"
+
+#: templates/wiki/book_detail.html:94
+msgid "This book cannot be published yet"
+msgstr "Ta książka nie może jeszcze zostać opublikowana"
+
+#: templates/wiki/book_edit.html:8
+#: templates/wiki/chunk_edit.html:8
+#: templates/wiki/document_details_base.html:35
+#: templates/wiki/pubmark_dialog.html:15
+#: templates/wiki/tag_dialog.html:15
+msgid "Save"
+msgstr "Zapisz"
+
+#: templates/wiki/chunk_add.html:8
+msgid "Add chunk"
+msgstr "Dodaj część"
+
#: templates/wiki/diff_table.html:5
msgid "Old version"
msgstr "Stara wersja"
msgid "Click to open/close gallery"
msgstr "Kliknij, aby (ro)zwinąć galerię"
-#: templates/wiki/document_details_base.html:36
+#: templates/wiki/document_details_base.html:31
msgid "Help"
msgstr "Pomoc"
-#: templates/wiki/document_details_base.html:38
+#: templates/wiki/document_details_base.html:33
msgid "Version"
msgstr "Wersja"
-#: templates/wiki/document_details_base.html:38
+#: templates/wiki/document_details_base.html:33
msgid "Unknown"
msgstr "nieznana"
-#: templates/wiki/document_details_base.html:40
-#: templates/wiki/tag_dialog.html:15
-msgid "Save"
-msgstr "Zapisz"
-
-#: templates/wiki/document_details_base.html:41
+#: templates/wiki/document_details_base.html:36
msgid "Save attempt in progress"
msgstr "Trwa zapisywanie"
-#: templates/wiki/document_details_base.html:42
+#: templates/wiki/document_details_base.html:37
msgid "There is a newer version of this document!"
msgstr "Istnieje nowsza wersja tego dokumentu!"
-#: templates/wiki/document_list.html:30
+#: templates/wiki/document_list.html:31
msgid "Clear filter"
msgstr "Wyczyść filtr"
-#: templates/wiki/document_list.html:48
+#: templates/wiki/document_list.html:46
+msgid "No books found."
+msgstr "Nie znaleziono książek."
+
+#: templates/wiki/document_list.html:89
msgid "Your last edited documents"
msgstr "Twoje ostatnie edycje"
-#: templates/wiki/document_upload.html:9
+#: templates/wiki/document_upload.html:8
msgid "Bulk documents upload"
msgstr "Hurtowe dodawanie dokumentów"
-#: templates/wiki/document_upload.html:12
+#: templates/wiki/document_upload.html:11
msgid "Please submit a ZIP with UTF-8 encoded XML files. Files not ending with <code>.xml</code> will be ignored."
msgstr "Proszę wskazać archiwum ZIP z plikami XML w kodowaniu UTF-8. Pliki nie kończące się na <code>.xml</code> zostaną zignorowane."
-#: templates/wiki/document_upload.html:17
+#: templates/wiki/document_upload.html:16
+#: templatetags/wiki.py:36
msgid "Upload"
-msgstr "Dodaj"
+msgstr "Załaduj"
-#: templates/wiki/document_upload.html:24
+#: templates/wiki/document_upload.html:23
msgid "There have been some errors. No files have been added to the repository."
msgstr "Wystąpiły błędy. Żadne pliki nie zostały dodane do repozytorium."
-#: templates/wiki/document_upload.html:25
+#: templates/wiki/document_upload.html:24
msgid "Offending files"
msgstr "Błędne pliki"
-#: templates/wiki/document_upload.html:33
+#: templates/wiki/document_upload.html:32
msgid "Correct files"
msgstr "Poprawne pliki"
-#: templates/wiki/document_upload.html:44
+#: templates/wiki/document_upload.html:43
msgid "Files have been successfully uploaded to the repository."
msgstr "Pliki zostały dodane do repozytorium."
-#: templates/wiki/document_upload.html:45
+#: templates/wiki/document_upload.html:44
msgid "Uploaded files"
msgstr "Dodane pliki"
-#: templates/wiki/document_upload.html:55
+#: templates/wiki/document_upload.html:54
msgid "Skipped files"
msgstr "Pominięte pliki"
-#: templates/wiki/document_upload.html:56
+#: templates/wiki/document_upload.html:55
msgid "Files skipped due to no <code>.xml</code> extension"
msgstr "Pliki pominięte z powodu braku rozszerzenia <code>.xml</code>."
+#: templates/wiki/pubmark_dialog.html:16
+#: templates/wiki/revert_dialog.html:39
#: templates/wiki/tag_dialog.html:16
msgid "Cancel"
msgstr "Anuluj"
+#: templates/wiki/revert_dialog.html:38
+msgid "Revert"
+msgstr "Przywróć"
+
+#: templates/wiki/user_list.html:7
+#: templatetags/wiki.py:33
+msgid "Users"
+msgstr "Użytkownicy"
+
#: templates/wiki/tabs/annotations_view.html:9
msgid "all"
msgstr "wszystkie"
+#: templates/wiki/tabs/annotations_view_item.html:3
+msgid "Annotations"
+msgstr "Przypisy"
+
#: templates/wiki/tabs/gallery_view.html:7
msgid "Previous"
msgstr "Poprzednie"
msgstr "Porównaj wersje"
#: templates/wiki/tabs/history_view.html:7
-msgid "Mark version"
-msgstr "Oznacz wersję"
+msgid "Mark for publishing"
+msgstr "Oznacz do publikacji"
#: templates/wiki/tabs/history_view.html:9
msgid "Revert document"
msgid "Source code"
msgstr "Kod źródłowy"
-#: templates/wiki/tabs/summary_view.html:10
+#: templates/wiki/tabs/summary_view.html:9
msgid "Title"
msgstr "Tytuł"
-#: templates/wiki/tabs/summary_view.html:15
+#: templates/wiki/tabs/summary_view.html:14
msgid "Document ID"
msgstr "ID dokumentu"
-#: templates/wiki/tabs/summary_view.html:19
+#: templates/wiki/tabs/summary_view.html:18
msgid "Current version"
msgstr "Aktualna wersja"
-#: templates/wiki/tabs/summary_view.html:22
+#: templates/wiki/tabs/summary_view.html:21
msgid "Last edited by"
msgstr "Ostatnio edytowane przez"
-#: templates/wiki/tabs/summary_view.html:26
+#: templates/wiki/tabs/summary_view.html:25
msgid "Link to gallery"
msgstr "Link do galerii"
-#: templates/wiki/tabs/summary_view.html:31
-msgid "Publish"
-msgstr "Opublikuj"
-
-#: templates/wiki/tabs/summary_view_item.html:4
+#: templates/wiki/tabs/summary_view_item.html:3
msgid "Summary"
msgstr "Podsumowanie"
msgid "Visual editor"
msgstr "Edytor wizualny"
+#: templatetags/wiki.py:30
+msgid "Assigned to me"
+msgstr "Przypisane do mnie"
+
+#: templatetags/wiki.py:32
+msgid "Unassigned"
+msgstr "Nie przypisane"
+
+#: templatetags/wiki.py:34
+msgid "All"
+msgstr "Wszystkie"
+
+#: templatetags/wiki.py:35
+msgid "Add"
+msgstr "Dodaj"
+
+#: templatetags/wiki.py:39
+msgid "Admin"
+msgstr "Administracja"
+
+#~ msgid "First correction"
+#~ msgstr "Autokorekta"
+
+#~ msgid "Tagging"
+#~ msgstr "Tagowanie"
+
+#~ msgid "Initial Proofreading"
+#~ msgstr "Korekta"
+
+#~ msgid "Annotation Proofreading"
+#~ msgstr "Sprawdzenie przypisów źródła"
+
+#~ msgid "Modernisation"
+#~ msgstr "Uwspółcześnienie"
+
+#~ msgid "Themes"
+#~ msgstr "Motywy"
+
+#~ msgid "Editor's Proofreading"
+#~ msgstr "Ostateczna redakcja literacka"
+
+#~ msgid "Technical Editor's Proofreading"
+#~ msgstr "Ostateczna redakcja techniczna"
+
+#~ msgid "Finished stage: %s"
+#~ msgstr "Ukończony etap: %s"
+
#~ msgid "Refresh"
#~ msgstr "Odśwież"
+
#~ msgid "Insert special character"
#~ msgstr "Wstaw znak specjalny"
-
--- /dev/null
+# -*- coding: utf-8 -*-
+
+import csv
+from optparse import make_option
+import re
+import sys
+import urllib
+import urllib2
+
+from django.contrib.auth.models import User
+from django.core.management.base import BaseCommand
+from django.core.management.color import color_style
+from django.db import transaction
+
+from slughifi import slughifi
+from wiki.models import Chunk
+
+
+REDMINE_CSV = 'http://redmine.nowoczesnapolska.org.pl/projects/wl-publikacje/issues.csv'
+REDAKCJA_URL = 'http://redakcja.wolnelektury.pl/documents/'
+
+
+class Command(BaseCommand):
+ option_list = BaseCommand.option_list + (
+ make_option('-r', '--redakcja', dest='redakcja', metavar='URL',
+ help='Base URL of Redakcja documents',
+ default=REDAKCJA_URL),
+ make_option('-q', '--quiet', action='store_false', dest='verbose', default=True,
+ help='Less output'),
+ make_option('-f', '--force', action='store_true', dest='force', default=False,
+ help='Force assignment overwrite'),
+ )
+ help = 'Imports ticket assignments from Redmine.'
+ args = '[redmine-csv-url]'
+
+ def handle(self, *redmine_csv, **options):
+
+ self.style = color_style()
+
+ redakcja = options.get('redakcja')
+ verbose = options.get('verbose')
+ force = options.get('force')
+
+ if not redmine_csv:
+ if verbose:
+ print "Using default Redmine CSV URL:", REDMINE_CSV
+ redmine_csv = REDMINE_CSV
+
+ # Start transaction management.
+ transaction.commit_unless_managed()
+ transaction.enter_transaction_management()
+ transaction.managed(True)
+
+ redakcja_link = re.compile(re.escape(redakcja) + r'([-_.:?&%/a-zA-Z0-9]*)')
+
+ all_tickets = 0
+ all_chunks = 0
+ done_tickets = 0
+ done_chunks = 0
+ empty_users = 0
+ unknown_users = 0
+ unknown_books = 0
+ forced = 0
+
+ if verbose:
+ print 'Downloading CSV file'
+ for r in csv.reader(urllib2.urlopen(redmine_csv)):
+ if r[0] == '#':
+ continue
+ all_tickets += 1
+
+ username = r[6]
+ if not username:
+ if verbose:
+ print "Empty user, skipping"
+ empty_users += 1
+ continue
+
+ first_name, last_name = unicode(username, 'utf-8').rsplit(u' ', 1)
+ try:
+ user = User.objects.get(first_name=first_name, last_name=last_name)
+ except User.DoesNotExist:
+ print self.style.ERROR('Unknown user: ' + username)
+ print "'%s' '%s'" % (first_name, last_name)
+ print type(last_name)
+ unknown_users += 1
+ continue
+
+ ticket_done = False
+ for fname in redakcja_link.findall(r[-1]):
+ fname = unicode(urllib.unquote(fname), 'utf-8', 'ignore')
+ if fname.endswith('.xml'):
+ fname = fname[:-4]
+ fname = fname.replace(' ', '_')
+ fname = slughifi(fname)
+
+ chunks = Chunk.objects.filter(book__slug=fname)
+ if not chunks:
+ print self.style.ERROR('Unknown book: ' + fname)
+ unknown_books += 1
+ continue
+ all_chunks += chunks.count()
+
+ for chunk in chunks:
+ if chunk.user:
+ if chunk.user == user:
+ continue
+ else:
+ forced += 1
+ if force:
+ print self.style.WARNING(
+ '%s assigned to %s, forcing change to %s.' %
+ (chunk.pretty_name(), chunk.user, user))
+ else:
+ print self.style.WARNING(
+ '%s assigned to %s not to %s, skipping.' %
+ (chunk.pretty_name(), chunk.user, user))
+ continue
+ chunk.user = user
+ chunk.save()
+ ticket_done = True
+ done_chunks += 1
+
+ if ticket_done:
+ done_tickets += 1
+
+
+ # Print results
+ print
+ print "Results:"
+ print "Done %d/%d tickets, assigned %d/%d book chunks." % (
+ done_tickets, all_tickets, done_chunks, all_chunks)
+ print "%d tickets unassigned, for %d chunks assignment differed." % (
+ empty_users, forced)
+ print "Unrecognized: %d books, %d users." % (
+ unknown_books, unknown_users)
+ print
+
+
+ transaction.commit()
+ transaction.leave_transaction_management()
+
from slughifi import slughifi
META_REGEX = re.compile(r'\s*<!--\s(.*?)-->', re.DOTALL | re.MULTILINE)
+STAGE_TAGS_RE = re.compile(r'^#stage-finished: (.*)$', re.MULTILINE)
def urlunquote(url):
description=''
)
chunk.head = head
+ try:
+ chunk.stage = orm['dvcs.Tag'].objects.order_by('ordering')[0]
+ except IndexError:
+ chunk.stage = None
old_data = ''
maxrev = entry.filerev()
- gallery_link = None;
+ gallery_link = None
+
for rev in xrange(maxrev + 1):
- # TODO: tags
fctx = entry.filectx(rev)
data = fctx.data()
gallery_link = gallery(fname, data)
data = plain_text(data)
+
+ # get tags from description
+ description = fctx.description().decode("utf-8", 'replace')
+ tags = STAGE_TAGS_RE.findall(description)
+ tags = [orm['dvcs.Tag'].objects.get(slug=slug.strip()) for slug in tags]
+
+ if tags:
+ max_ordering = max(tags, key=lambda x: x.ordering).ordering
+ try:
+ chunk.stage = orm['dvcs.Tag'].objects.filter(ordering__gt=max_ordering).order_by('ordering')[0]
+ except IndexError:
+ chunk.stage = None
+
+ description = STAGE_TAGS_RE.sub('', description)
+
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=fctx.description().decode("utf-8", 'replace'),
+ description=description,
author_desc=fctx.user().decode("utf-8", 'replace'),
parent=chunk.head
)
+ head.tags = tags
chunk.head = head
old_data = data
+
chunk.save()
if gallery_link:
book.gallery = gallery_link
'Meta': {'object_name': 'Document'},
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'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'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
},
'dvcs.tag': {
'Meta': {'ordering': "['ordering']", 'object_name': 'Tag'},
<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">
+++ /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>
{% load i18n %}
{% load pagination_tags %}
+{% load wiki %}
{% block extrabody %}
{{ block.super }}
{% block leftcolumn %}
<form method="get" action="#">
- <table id="file-list">
+ <table>
<thead>
<tr><th>Filtr:</th>
<th><input autocomplete="off" name="filter" id="file-list-filter" type="text" size="40" /></th>
</tr>
</thead>
<tbody>
+ </tbody>
+ </table>
+ </form>
+
+
+
+ <form method="get" action="#">
+ <table id="file-list">
+ <tbody>
{% autopaginate books 20 %}
- {% for book in books %}
- {{ book.list_html }}
+ {% if not books %}
+ <tr><td>{% trans "No books found." %}</td></tr>
+ {% endif %}
+ {% for item in books %}
+ {% with item.book as book %}
+
+ {% ifequal book.chunk_set.count 1 %}
+ <tr>
+ <td><a target="_blank" href="{% url wiki_book book.slug %}">[B]</a></td>
+ <td><a href="{% url wiki_chunk_edit book.slug book.0.slug %}">[c]</a></td>
+ <td><a target="_blank"
+ href="{% url wiki_editor book.slug %}">
+ {{ book.title }}</a></td>
+ <td>({{ book.0.stage }})</td>
+ <td>{% if book.0.user %}<a href="{% url wiki_user book.0.user.username %}">{{ book.0.user.first_name }} {{ book.0.user.last_name }}</a>{% endif %}</td>
+ </tr>
+ {% else %}
+ <tr>
+ <td><a target="_blank" href="{% url wiki_book book.slug %}">[B]</a></td>
+ <td></td>
+ <td>{{ book.title }}</td>
+ </tr>
+ {% for chunk in item.chunks %}
+ <tr>
+ <td></td>
+ <td><a href="{% url wiki_chunk_edit book.slug chunk.slug %}">[c]</a></td>
+ <td><a target="_blank" href="{{ chunk.get_absolute_url }}">
+ <span class='chunkno'>{{ chunk.number }}.</span>
+ {{ chunk.comment }}</a></td>
+ <td>({{ chunk.stage }})</td>
+ <td>{% if chunk.user %}<a href="{% url wiki_user chunk.user.username %}">{{ chunk.user.first_name }} {{ chunk.user.last_name }}</a>{% endif %}</td>
+ </td></tr>
+ {% endfor %}
+ {% endifequal %}
+ {% endwith %}
{% endfor %}
- </tbody>
<tr><td colspan="3">{% paginate %}</td></tr>
+ </tbody>
</table>
</form>
{% endblock leftcolumn %}
+++ /dev/null
-<tr>
- <td colspan="3">
- <a target="_blank" data-id="{{ book.slug }}"
- href="{% url wiki_book book.slug %}">[?]</a>
- {% ifequal book.chunk_set.count 1 %}
- <a target="_blank" data-id="{{ book.slug }}"
- href="{% url wiki_editor book.slug %}">
- {{ book.title }}</a>
- {% else %}
- {{ book.title }}
- <div class="chunk-list">
- {% for chunk in book %}
- <a target="_blank" data-id="{{ book.slug }}"
- href="{{ chunk.get_absolute_url }}">
- <span class='chunkno'>{{ forloop.counter }}.</span>
- {{ chunk.comment }}</a><br/>
- {% endfor %}
- </div>
- {% endifequal %}
- </td>
-</tr>
<div class="toolbar">
<button type="button" id="make-diff-button"
data-enabled-when="2" disabled="disabled">{% trans "Compare versions" %}</button>
- <button type="button" id="tag-changeset-button"
- data-enabled-when="1" disabled="disabled">{% trans "Mark version" %}</button>
<button type="button" id="pubmark-changeset-button"
data-enabled-when="1" disabled="disabled">{% trans "Mark for publishing" %}</button>
<button type="button" id="doc-revert-button"
--- /dev/null
+{% extends "wiki/base.html" %}
+
+{% load i18n %}
+
+{% block leftcolumn %}
+
+<h1>{% trans "Users" %}</h1>
+
+<ul>
+{% for user in users %}
+ <li><a href="{% url wiki_user user.username %}">
+ <span class="chunkno">{{ forloop.counter }}.</span>
+ {{ user.first_name }} {{ user.last_name }}</a>
+ ({{ user.count }})</li>
+{% endfor %}
+</ul>
+
+{% endblock leftcolumn %}
tabs.append(Tab('my', _('Assigned to me'), reverse("wiki_user")))
tabs.append(Tab('unassigned', _('Unassigned'), reverse("wiki_unassigned")))
+ tabs.append(Tab('users', _('Users'), reverse("wiki_users")))
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")))
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'^users/$', 'users', name='wiki_users'),
url(r'^edit/(?P<slug>[^/]+)/(?:(?P<chunk>[^/]+)/)?$',
'editor', name="wiki_editor"),
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
+from django.db.models import Count
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, active_tab)
+from wiki import helpers
from django import http
from django.shortcuts import get_object_or_404, redirect
from django.http import Http404
@never_cache
def document_list(request):
return direct_to_template(request, 'wiki/document_list.html', extra_context={
- 'books': Book.objects.all(),
+ 'books': [helpers.BookChunks(b) for b in Book.objects.all()],
'last_books': sorted(request.session.get("wiki_last_books", {}).items(),
key=lambda x: x[1]['time'], reverse=True),
})
@active_tab('unassigned')
@never_cache
def unassigned(request):
+ chunks = Chunk.objects.filter(user=None).order_by('book__title', 'book', 'number')
+ books = []
+ book = None
+ for chunk in chunks:
+ if chunk.book != book:
+ book = chunk.book
+ books.append(helpers.ChoiceChunks(book, [chunk]))
+ else:
+ books[-1].chunks.append(chunk)
+
return direct_to_template(request, 'wiki/document_list.html', extra_context={
- 'books': Chunk.objects.filter(user=None),
+ 'books': books,
'last_books': sorted(request.session.get("wiki_last_books", {}).items(),
key=lambda x: x[1]['time'], reverse=True),
})
else:
user = get_object_or_404(User, username=username)
+ chunks = Chunk.objects.filter(user=user).order_by('book__title', 'number')
+ books = []
+ book = None
+ for chunk in chunks:
+ if chunk.book != book:
+ book = chunk.book
+ books.append(helpers.ChoiceChunks(book, [chunk]))
+ else:
+ books[-1].chunks.append(chunk)
+
return direct_to_template(request, 'wiki/document_list.html', extra_context={
- 'books': Chunk.objects.filter(user=user),
+ 'books': books,
'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))
+@active_tab('users')
+def users(request):
+ return direct_to_template(request, 'wiki/user_list.html', extra_context={
+ 'users': User.objects.all().annotate(count=Count('document')).order_by(
+ '-count', 'last_name', 'first_name'),
+ })
+
+
@never_cache
def editor(request, slug, chunk=None, template_name='wiki/document_details.html'):
try:
#file-list {
overflow: visible;
float: left;
- max-width: 50%;
+ /*max-width: 50%;*/
padding-right: 2%;
border-right: 1px dashed black;
.chunkno {
font-size: .7em;
+ padding-left: 2em;
}
td {
vertical-align: top;
}
-.chunk-list {
- padding-left: 2em;
-}
.fix {