From a7a2b1c6daaa2266645abc5ee4fac91ce10a4c39 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Tue, 21 Jun 2011 16:11:10 +0200 Subject: [PATCH] document stages on import, assigning documents to users, import assignments from redmine --- apps/dvcs/fixtures/stages.json | 83 ++++ apps/dvcs/migrations/0001_initial.py | 5 + apps/dvcs/models.py | 12 +- apps/wiki/forms.py | 8 +- apps/wiki/helpers.py | 25 ++ apps/wiki/locale/pl/LC_MESSAGES/django.mo | Bin 5088 -> 6633 bytes apps/wiki/locale/pl/LC_MESSAGES/django.po | 364 +++++++++++++----- apps/wiki/management/__init__.py | 0 apps/wiki/management/commands/__init__.py | 0 .../commands/assign_from_redmine.py | 142 +++++++ ...unique_chunk_book_number__add_unique_ch.py | 32 +- apps/wiki/templates/wiki/base.html | 4 - apps/wiki/templates/wiki/chunk_list_item.html | 9 - apps/wiki/templates/wiki/document_list.html | 51 ++- .../templates/wiki/document_list_item.html | 21 - .../templates/wiki/tabs/history_view.html | 2 - apps/wiki/templates/wiki/user_list.html | 18 + apps/wiki/templatetags/wiki.py | 1 + apps/wiki/urls.py | 1 + apps/wiki/views.py | 36 +- redakcja/static/css/filelist.css | 6 +- 21 files changed, 665 insertions(+), 155 deletions(-) create mode 100644 apps/dvcs/fixtures/stages.json create mode 100755 apps/wiki/management/__init__.py create mode 100755 apps/wiki/management/commands/__init__.py create mode 100755 apps/wiki/management/commands/assign_from_redmine.py delete mode 100755 apps/wiki/templates/wiki/chunk_list_item.html delete mode 100755 apps/wiki/templates/wiki/document_list_item.html create mode 100755 apps/wiki/templates/wiki/user_list.html diff --git a/apps/dvcs/fixtures/stages.json b/apps/dvcs/fixtures/stages.json new file mode 100644 index 00000000..fc05d579 --- /dev/null +++ b/apps/dvcs/fixtures/stages.json @@ -0,0 +1,83 @@ +[ + { + "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" + } + } +] diff --git a/apps/dvcs/migrations/0001_initial.py b/apps/dvcs/migrations/0001_initial.py index d9f0984c..6bff0950 100644 --- a/apps/dvcs/migrations/0001_initial.py +++ b/apps/dvcs/migrations/0001_initial.py @@ -4,6 +4,7 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models + class Migration(SchemaMigration): def forwards(self, orm): @@ -52,6 +53,10 @@ class Migration(SchemaMigration): )) 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): diff --git a/apps/dvcs/models.py b/apps/dvcs/models.py index a72556f6..f81f2cab 100644 --- a/apps/dvcs/models.py +++ b/apps/dvcs/models.py @@ -39,7 +39,14 @@ class Tag(models.Model): 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) @@ -220,6 +227,9 @@ class Document(models.Model): 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: diff --git a/apps/wiki/forms.py b/apps/wiki/forms.py index 3626b6d3..e153f7e8 100644 --- a/apps/wiki/forms.py +++ b/apps/wiki/forms.py @@ -3,12 +3,14 @@ # 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): """ @@ -154,6 +156,10 @@ class ChunkForm(forms.ModelForm): """ 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 diff --git a/apps/wiki/helpers.py b/apps/wiki/helpers.py index ee26c5a2..fe4b3b86 100644 --- a/apps/wiki/helpers.py +++ b/apps/wiki/helpers.py @@ -143,3 +143,28 @@ def active_tab(tab): 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 + diff --git a/apps/wiki/locale/pl/LC_MESSAGES/django.mo b/apps/wiki/locale/pl/LC_MESSAGES/django.mo index 1f5e5140300fe6d1738fdcfbb7d9fc5e450acd2d..f841945b2f770acbdbc63e6e93d5659c3ac0f72c 100644 GIT binary patch literal 6633 zcmai%Ym6P&UBC}%pu~lg7HS%3!wDgz#=h%ar#0@z4Oy?(@z(b4;=OAp?u&D0&fcA! zxpQvkk(-%*sBmL}3TmMOsaB(?QY#_R52y|K608ah@>78p@~1w@&riWmh5Fxt_fmci%Ftg61X-*QTR#tR@g%M?mE01em>Oy9z0I@Irt9v=TQ2+0%gDd8u&j@)^`t$KMC)HRH+`6 z@jeKp{jtEcz>h=emqWjfP`(a#ss9|5b$&0j--R-y{~;*-4?~*N{ZRCN6v{j&0?$C1 z|1x|xyb7h?7`_uuAb;w!{7Cy3p@v_FGS6Q_ndg;I{%0t5`7d}L{xAF`xPmesfMY2B z^96{?)fb_B{}t%{0`jN6!H@L24W<3hpzPz@kRjDS2EGdCDZdWI-bdJ+%zqY&Ue=&| ze>Idp0maXE;9+GuKnTR)`K6QTWYsAMbZ@1czMFHrXL8kGHrQN(}lfili} zp~S@zDBrC>{#2hInSTgnoDmd%{}hz<+zjO}!(X8MO~}&KccH|~e?yj}4l|k9>0v12 zpMX-o1f~CFNLMw0vW^;xoqiX}`ksd}{vX0$gx`k00$+pj-AR-x89{CQGb^Ryg&sR#nchM+%d;s1DkHVjZD^T|JF(~WK zpv>DqS=XoGXW(Z;`Cgnx#<>s5_zyx^_bDj-9}m0$Wq((o=qrJu_coM&J(RxyF|E28 z>c0l>r+f>Zfd2qxKlid&AIDJUIU0Bpo};`3MZdoZAAx@aWxnr1+25;B^!UBNyHJ{p z_qM=yL+Sqzl>Wz{%=>8I1t{zJ2t*a?b5Qp6RVd@W2t_a74CQY@S4pMST1UvVh1wKZ0x_vQ~NIEW3tW zMJ^zhkm>UGIfop4-cP|I zV#||=#OzUI6_Mw32k(ROdJd6%DUZah#L`Elz_W&kjekxGJRd`T)xTj!_;`4~94LMz zwwFgEk0BDvV&6U@&nEJuf9rmRK>S^N;vyox^eFOi6Pa*OQkOVo8oI+ycEyyxLXfjzGi|A;l&Qsn-Nv@W% zOfBWPt4x)+yi`l$vCU&WaE>0`d*$}uw5xV(F>B5my`4N``K&CHVQynxIX$v!sjhZh z5%6%S?Z_mVI#XwQ?P)nvIT`CN@aS-298IWW4NKoGFvoi*^S1gu=;6Rlzx{| zk=e>JyDJJCRWb_OSZ4gn&eo`wYg+Sa`k^{&%cw{O78RO&XiMF=T8~U@=k}XWkYlvS7&J6>aG5{-YISK$i+6EQ_@=M9rLuM z(dN3WqsW%!cAcUAPKll3yP3xh6}qCCepsdnc8qmgTTxH$^l2IRvAJhP+3Dl{6@^x! zd6%nmg&XOpE=tUIjv4fmmoBO&f*#NJFI}81`n=7?>O6*EF15PtRS`|~s*TQ)ZS>Sc zvbD+#?J=yIiK>%oPOau8TG3|adD9y9fd5=HWuOsT3Z^uJ%&NqoMnd(HWjLQ}&irmDf{Es$OWk+Ldlk0Ke zh6VnmHi@oiCje8$_;NSbW^k!aQ=11vvo0~2`29l+@TLZaXN;MHZo0aNa1z{6ZPp`J z)u{fH{h5yYhM12D0@Ww$*n=_PMpoORa78(%F|A+8fp-6u_{jIiL^lu##pv8lNM*ss z+HH4`Fd^iZaABgp$(}6lcf=J8r^ehJ|_BRHVbj zBi#qtfe@PRsqC6^Lx_pL%CgioN5pdyc)Ge$Ori&-Orn|N5WqzpRdr#zMmxliRgsK1 zL57;(_SJH3ys?tA#UCW{Q>sDXQqtFSF{;a<_+m-^mQk>mlAu?9fs(QFN_EhAJsObZ zOWAUWd+ob*3B&)Es`3WmSa#(KZ!&j|vlcb4N~QJ%|Mxq2bbf(;lI(i@!sI2ZaK)m&%z={X<<{(`MxQQB>}Z+HMZV&3 zw&tSNmbn?btW3?ED~5C9>@mj4hc$_|*SBW0sLzq+OtfnVkLd?`!+)VqZ-=%YJQy3k zw0db}UsVfp^M{sQ&UwM2n=!i=tsW;aB>AI~O^ec2AM#0Xzn^Sw+ZMeQIn(f&MSW_J zREIbbW3$`+>ZrYQbMH%cextjXaIO@xdUdsIo3ct1i{aX4oRkgy_paZ$5w$uklRG!| zZl!l_?$^cc;5&|;+ud2mL|tuCmz!PPjuMkM(=kmhhrS-=OvBxU5M1fWl|>sV7)-^{%??+T!IG_HN|~<4+QsrB3$4LFn%%VSBpORWtJU znZ%CtZoPL)vsuR6wX7~`8~+iZSrzI+mZW*IdrX@_qu*D!Bkd%~@7!QeV!##&8{cqD zI*~1r%}U1DV%le;*5!`2abYIxZOk}{+NvfmzfiQZwX3DHBJ1R)`_ypGC1tD22>~)y zP**i}d>L~zw9SO+BFi2*#Lv!#s?}AQ-DtVjs12sme3P&%4x7ZX;MB#gQ=Rt>PBmGR zZXK6{z3YuvZD$2JA=(DLC-rFBZR|)jY?sSfDWHyhN5mvyU`3l3TvxhULhX!@|-`%*SrsII5#f)3QQaw&5*`WHn90n1Yb268H^;eEYj`NVGux7++|>PT%C(2IF8*6*cDQ%lb!Nuv z&k#~K|6w|*R8)1dBx!u_;zb!M!{|6UX&7oPq+}K2UT>9 zrP#e^@dQsM@nJ8HOtz7%(!F+3KuCq1IFsD6R2TX}E1C#%i2PRU=_h`xC5 zC5@AWsc@mGyNWK7?kZFnwp|*6-td1=X1tzixhb6u*+g?;3CW>;V`|V7e{tsvU=B+Eyq`9Rb1zQ%Nx~is(SCbcVEdh zXqq5Ve2gi)9rmu97(4q-&C=T5t)?Po@+4})&biDCBvvNkvsiRR0UUGp?oY0_aXM`M@x{BNVG&bq;zT>`Fb%D;L8%dr#o-l+crJ&Vp9 literal 5088 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 diff --git a/apps/wiki/locale/pl/LC_MESSAGES/django.po b/apps/wiki/locale/pl/LC_MESSAGES/django.po index 0b102e90..c760f3a7 100644 --- a/apps/wiki/locale/pl/LC_MESSAGES/django.po +++ b/apps/wiki/locale/pl/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" 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 \n" "Language-Team: Fundacja Nowoczesna Polska \n" "Language: \n" @@ -16,121 +16,223 @@ msgstr "" "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" @@ -147,87 +249,102 @@ msgstr "Utwórz dokument" 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 .xml will be ignored." msgstr "Proszę wskazać archiwum ZIP z plikami XML w kodowaniu UTF-8. Pliki nie kończące się na .xml 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 .xml extension" msgstr "Pliki pominięte z powodu braku rozszerzenia .xml." +#: 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" @@ -253,8 +370,8 @@ msgid "Compare versions" 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" @@ -301,31 +418,27 @@ msgstr "Znajdź i zamień" 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" @@ -341,8 +454,55 @@ msgstr "Wstaw przypis" 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" - diff --git a/apps/wiki/management/__init__.py b/apps/wiki/management/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/apps/wiki/management/commands/__init__.py b/apps/wiki/management/commands/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/apps/wiki/management/commands/assign_from_redmine.py b/apps/wiki/management/commands/assign_from_redmine.py new file mode 100755 index 00000000..45177497 --- /dev/null +++ b/apps/wiki/management/commands/assign_from_redmine.py @@ -0,0 +1,142 @@ +# -*- 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() + diff --git a/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py b/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py index 010ed2a6..3db141ae 100644 --- a/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py +++ b/apps/wiki/migrations/0003_auto__add_book__add_chunk__add_unique_chunk_book_number__add_unique_ch.py @@ -14,6 +14,7 @@ from south.v2 import SchemaMigration from slughifi import slughifi META_REGEX = re.compile(r'\s*', re.DOTALL | re.MULTILINE) +STAGE_TAGS_RE = re.compile(r'^#stage-finished: (.*)$', re.MULTILINE) def urlunquote(url): @@ -93,27 +94,48 @@ def migrate_file_from_hg(orm, fname, entry): 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 @@ -246,7 +268,9 @@ class Migration(SchemaMigration): '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'}, diff --git a/apps/wiki/templates/wiki/base.html b/apps/wiki/templates/wiki/base.html index 85abaaf4..5d20bbca 100644 --- a/apps/wiki/templates/wiki/base.html +++ b/apps/wiki/templates/wiki/base.html @@ -16,10 +16,6 @@
{% main_tabs %} -
diff --git a/apps/wiki/templates/wiki/chunk_list_item.html b/apps/wiki/templates/wiki/chunk_list_item.html deleted file mode 100755 index bec9e75a..00000000 --- a/apps/wiki/templates/wiki/chunk_list_item.html +++ /dev/null @@ -1,9 +0,0 @@ - - - [?] - - {{ chunk.pretty_name }} - - diff --git a/apps/wiki/templates/wiki/document_list.html b/apps/wiki/templates/wiki/document_list.html index 221b63d2..9525078c 100644 --- a/apps/wiki/templates/wiki/document_list.html +++ b/apps/wiki/templates/wiki/document_list.html @@ -2,6 +2,7 @@ {% load i18n %} {% load pagination_tags %} +{% load wiki %} {% block extrabody %} {{ block.super }} @@ -23,7 +24,7 @@ $(function() { {% block leftcolumn %}
- +
@@ -31,12 +32,54 @@ $(function() { + +
Filtr:
+
+ + + +
+ + {% autopaginate books 20 %} - {% for book in books %} - {{ book.list_html }} + {% if not books %} + + {% endif %} + {% for item in books %} + {% with item.book as book %} + + {% ifequal book.chunk_set.count 1 %} + + + + + + + + {% else %} + + + + + + {% for chunk in item.chunks %} + + + + + + + + {% endfor %} + {% endifequal %} + {% endwith %} {% endfor %} - +
{% trans "No books found." %}
[B][c] + {{ book.title }}({{ book.0.stage }}){% if book.0.user %}{{ book.0.user.first_name }} {{ book.0.user.last_name }}{% endif %}
[B]{{ book.title }}
[c] + {{ chunk.number }}. + {{ chunk.comment }}({{ chunk.stage }}){% if chunk.user %}{{ chunk.user.first_name }} {{ chunk.user.last_name }}{% endif %}
{% paginate %}
{% endblock leftcolumn %} diff --git a/apps/wiki/templates/wiki/document_list_item.html b/apps/wiki/templates/wiki/document_list_item.html deleted file mode 100755 index f1c4d377..00000000 --- a/apps/wiki/templates/wiki/document_list_item.html +++ /dev/null @@ -1,21 +0,0 @@ - - - [?] - {% ifequal book.chunk_set.count 1 %} - - {{ book.title }} - {% else %} - {{ book.title }} -
- {% for chunk in book %} - - {{ forloop.counter }}. - {{ chunk.comment }}
- {% endfor %} -
- {% endifequal %} - - diff --git a/apps/wiki/templates/wiki/tabs/history_view.html b/apps/wiki/templates/wiki/tabs/history_view.html index db207bb1..0764f98b 100644 --- a/apps/wiki/templates/wiki/tabs/history_view.html +++ b/apps/wiki/templates/wiki/tabs/history_view.html @@ -3,8 +3,6 @@
-