From 730399e901c72a552011d6c0a35bf41492590a8b Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 27 Mar 2014 13:20:29 +0100 Subject: [PATCH 1/1] Add projects for images and port mass_edit. Also: remove the ability to mass set things as publishable, page the user list in mass-edit so that it fits vertically, include image actions on wall, show username for users without first and last names. --- apps/catalogue/forms.py | 2 +- .../catalogue/locale/pl/LC_MESSAGES/django.mo | Bin 7862 -> 7731 bytes .../catalogue/locale/pl/LC_MESSAGES/django.po | 150 +++++++------- .../0013_auto__add_field_image_project.py | 196 ++++++++++++++++++ apps/catalogue/models/image.py | 2 + .../templates/catalogue/book_list/book.html | 3 +- .../catalogue/book_list/book_list.html | 11 +- .../templates/catalogue/book_list/chunk.html | 3 +- .../templates/catalogue/image_list.html | 9 + .../templates/catalogue/image_short.html | 5 +- .../templates/catalogue/image_table.html | 35 +++- .../templates/catalogue/user_list.html | 3 +- apps/catalogue/templates/catalogue/wall.html | 3 +- apps/catalogue/templatetags/book_list.py | 11 +- apps/catalogue/templatetags/common_tags.py | 4 + apps/catalogue/templatetags/wall.py | 57 ++++- apps/catalogue/urls.py | 2 + apps/catalogue/views.py | 134 +++++++----- redakcja/static/js/catalogue/book_list.js | 176 ++++++++-------- redakcja/static/js/wiki_img/wikiapi.js | 12 ++ 20 files changed, 581 insertions(+), 237 deletions(-) create mode 100644 apps/catalogue/migrations/0013_auto__add_field_image_project.py diff --git a/apps/catalogue/forms.py b/apps/catalogue/forms.py index 83b16523..a2ae86ad 100644 --- a/apps/catalogue/forms.py +++ b/apps/catalogue/forms.py @@ -175,7 +175,7 @@ class ImageForm(forms.ModelForm): class ReadonlyImageForm(ImageForm): - """Form used for not editing a Book.""" + """Form used for not editing an Image.""" def __init__(self, *args, **kwargs): ret = super(ReadonlyImageForm, self).__init__(*args, **kwargs) diff --git a/apps/catalogue/locale/pl/LC_MESSAGES/django.mo b/apps/catalogue/locale/pl/LC_MESSAGES/django.mo index 64f78b46d130961bc428e67d7e9bd30090dbe47a..17689b80911f5fcaae5ddb9b231a6e4c2d3ac7e6 100644 GIT binary patch delta 2800 zcmYk-eN5F=9LMnkTm-HN!ZlPNxu$qUtRNInK@5_v74&d5OUWm^%9E1dl}z;h;U+n1 zv(PnLV{Eut&VTH-(n!|``XkF=7He9q7UhO*y0*sbiQb=k56v^azt=gx-#NeY_`7^i z8Y&6?km@*LNC$~b!r?IHH2xOHh4hNkm^3_!v#~2h~vy-ivuyjMZ3x9jK1`kUulPMeT-B1O5)x z{w8XmzoS;}PjsP+(Q05GOrn2NKqeK-Q7>ADYPbcp5_Q%?m`wRNYD-SxbnL@L_=SBw zZjEC!>S!ivW#?f77NgqtVo)7@L`D_+QROSBk&YmPHe;wI8%GW3Z`7WrG8(N!CThvE zk-kk4YR0S4jhj&K4_Z4>_1{cp{Z-*zZg}x?RN2L}G@~V`rQD44X?9>N1~3;7U^<>g z4Wu76(95U^454N|ifVTU^}Y$zM5m;%{(6waa8z*yYKA$eie=VHRJ|(H41Kn|71eGh zs$Dy(-5aQZoV0eM+V!H|a}HJS!=TMvvK0nVBfE;4(RKTL6t#pmQANp?OQ6Z|M5_`YG-uGg7ORDXI4VW0sQsaX(XkuC(d>d790QJHl)K-k32J#DP zsc)g`#jp$+n2efnE~?%#WOq#kQq}m7uPbQkA{lc8^`cWaAJ3y!;Cs{yenov9w^0N5 z%RYBV>ta4g#op?Wh5DpblpbYG8fHn9UW;!ck1q_wS&#Mw)?Y=;5LzT!pi-2KAzS z$e($gOCFv<4dgm%NyktFn6PChjSo}KLOt(AovrhzdY@oWOM96Nf94x5n$a!PjH2jO z{}bX-4YE-)$wLNjDo}@TBhJAldoqK*d;_(FS&T~cmZB!G5_zZbB2`SSy&ptP=}GMYsulCE-N> z|EE%NPubE6>+`7n(;=!Lo+ESsbBRSn4e=P^BMuTvi3Wo0HA@KXc_VRm(kH1iq!jLd zGZ`J0$@H+z=s+szWUnOnAv7BZ9Uz^4rQH$Cc6^e^C-&HTVin;h^aB(i783J`X9<3% z(#;cOa)^z@GejE^LwG_Lox{-y%`JX+pw-{f+V$SFcS8Q8_Z@LX?)-w~`Gs9>*Ib(~ r3VB`Wv1#k;2Ts=d8{C1xkN59wY;N0K-}q^$t?SiUL!n)>*Tnt@+)VBr delta 2959 zcmZwJdrZ}39LMoT6a_+%n<7FU!B9cqa0wMK6-WW&5``C(@F2%HTn=|Hq@9^*E5_V3 zYufxnY|eH0L(gh%nZ_1wiP&kzypQ1_e33p0GiEl9U_5?}y7ebc#RnLQV>Tc1h%tOjIA1D{ z$5>3Z<;##ROv(6tpDE*FCIz*qirX*_`!NCsF$GWHbi9N!a1=F=FHq0lwD<2|6!~9} zkNKA`Js%p*pfH0k4WIx+HSJaQMmaJGvjNqS3zM(~m*XMK#mlIU|3W_IAzykflu>BF zv8d-$Py8> z({MiOeg$e^^)~NDb=;5YXFvK{xp;#MH8h2%)L}fTqQmBwqDG#FnsFIw3F}Y;t4Hm1 z7iwh&P+M>S8JjtVT7lE(z>BE%zl&u3b#adZJ@AjMFoWrokzb4s>_*M(2x@6RM#gMD z#bCUF>G%yMU@(noAP&?(m!Kw)iJEya>bZ?ktiKv;pg=Qkwl~^s#U9iQUqRJ7X?+{j zz`Lj!p0oMOs18O^&)q^j_Xlbq_pJ|6&rR{M@oFd%RWZ(*h^ml+8dx@JMl0<7V${l& zqn5r7nY?L4ZBZA}huMef_%N!U*HQhPu;so}_Qn}hgYVfJ7ce}CrN%7EKWAEt@Byk` zGSgFonW(MELk*+^wbYfUdM=!Y9jFPtimLY}vfDm$iVH2-In?WR#d-(TP!K0`AT!mXu9lwQY@C<4I=TS>Og6iM~s@^TsfPO$7&N0-$=294^_kSrD^RZY3*o0b< z-KY+RkdHaemzMH8&c!cL4gQ3D%v1`Un1~usCF)FUMYY#~8qiBNKZL#m6b##fR9e$v zD@0W+L9Iv?QpIdS&9DbG!2P2q;%Gba&jsolWhyya67S%7_enRd)i0nEl|=HOr*fJkZp@fgGnDb;z{8X~bqiTjwF3APNY*Jxcn0c$#2W zO#_iZ=uJ@nfnT-dSgp*Y6vK59p>t6?sa%&jbj`$L#FK;$@kFZNqRwWXM=#;9`3Zu! zSg&Rmaj}+IN-Q9B$~y`DF7y*?2&EPxkJze=P0vkSpiXrSQRzPzc0FjJtEbK3?d)@O z^*6P9dRtsg?QT=4!bt^38)u#ktL|%Y_c;1{-97&45g$y;%6DYv7i8zAJF}h6u$tD&@dU^hzqZ5MDs+$MAuI&Sk=Fai<+g#gQJ*N79 g3XdklUz=6#_3m->k6zr<*Vehq>uK}fi?0a&59;a-lmGw# diff --git a/apps/catalogue/locale/pl/LC_MESSAGES/django.po b/apps/catalogue/locale/pl/LC_MESSAGES/django.po index d98440f3..64ddd9f4 100644 --- a/apps/catalogue/locale/pl/LC_MESSAGES/django.po +++ b/apps/catalogue/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: 2014-03-26 16:13+0100\n" -"PO-Revision-Date: 2014-03-26 16:14+0100\n" +"POT-Creation-Date: 2014-03-27 13:16+0100\n" +"PO-Revision-Date: 2014-03-27 13:17+0100\n" "Last-Translator: Radek Czajka \n" "Language-Team: Fundacja Nowoczesna Polska \n" @@ -61,23 +61,23 @@ msgstr "Dokument o tym slugu już istnieje w repozytorium." msgid "File should be UTF-8 encoded." msgstr "Plik powinien mieć kodowanie UTF-8." -#: views.py:552 models/book.py:56 +#: views.py:576 models/book.py:56 msgid "books" msgstr "książki" -#: views.py:554 +#: views.py:578 msgid "scan gallery" msgstr "galeria skanów" -#: models/book.py:28 models/chunk.py:23 models/image.py:21 +#: models/book.py:28 models/chunk.py:23 models/image.py:22 msgid "title" msgstr "tytuł" -#: models/book.py:29 models/chunk.py:24 models/image.py:22 +#: models/book.py:29 models/chunk.py:24 models/image.py:23 msgid "slug" msgstr "slug" -#: models/book.py:30 models/image.py:23 +#: models/book.py:30 models/image.py:24 msgid "public" msgstr "publiczna" @@ -105,19 +105,19 @@ msgstr "Książka nie ma części." msgid "Not all chunks have publishable revisions." msgstr "Niektóre części nie są gotowe do publikacji." -#: models/book.py:266 models/image.py:80 +#: models/book.py:266 models/image.py:82 msgid "Invalid XML" msgstr "Nieprawidłowy XML" -#: models/book.py:268 models/image.py:82 +#: models/book.py:268 models/image.py:84 msgid "No Dublin Core found." msgstr "Brak sekcji Dublin Core." -#: models/book.py:270 models/image.py:84 +#: models/book.py:270 models/image.py:86 msgid "Invalid Dublin Core" msgstr "Nieprawidłowy Dublin Core" -#: models/book.py:273 models/image.py:88 +#: models/book.py:273 models/image.py:90 msgid "rdf:about is not" msgstr "rdf:about jest różny od" @@ -137,15 +137,15 @@ msgstr "część" msgid "chunks" msgstr "części" -#: models/image.py:20 models/image.py:34 models/publish_log.py:45 +#: models/image.py:21 models/image.py:36 models/publish_log.py:45 msgid "image" msgstr "obraz" -#: models/image.py:35 +#: models/image.py:37 msgid "images" msgstr "obrazy" -#: models/image.py:73 +#: models/image.py:75 msgid "There is no publishable revision" msgstr "Żadna wersja nie została oznaczona do publikacji." @@ -157,7 +157,8 @@ msgstr "nazwa" msgid "notes" msgstr "notatki" -#: models/project.py:19 templates/catalogue/book_list/book_list.html:64 +#: models/project.py:19 templates/catalogue/image_table.html:58 +#: templates/catalogue/book_list/book_list.html:65 msgid "project" msgstr "projekt" @@ -170,7 +171,7 @@ msgid "time" msgstr "czas" #: models/publish_log.py:19 models/publish_log.py:47 -#: templates/catalogue/wall.html:19 +#: templates/catalogue/wall.html:20 msgid "user" msgstr "użytkownik" @@ -236,7 +237,8 @@ msgid "Chunks" msgstr "Części" #: templates/catalogue/book_detail.html:49 -#: templates/catalogue/image_detail.html:36 templatetags/wall.py:78 +#: templates/catalogue/image_detail.html:36 templatetags/wall.py:108 +#: templatetags/wall.py:129 msgid "Publication" msgstr "Publikacja" @@ -319,8 +321,8 @@ msgid "Add chunk" msgstr "Dodaj część" #: templates/catalogue/chunk_edit.html:5 templates/catalogue/chunk_edit.html:9 -#: templates/catalogue/book_list/book.html:8 -#: templates/catalogue/book_list/chunk.html:6 +#: templates/catalogue/book_list/book.html:9 +#: templates/catalogue/book_list/chunk.html:7 msgid "Chunk settings" msgstr "Ustawienia części" @@ -399,43 +401,44 @@ msgstr "Edytor" msgid "Proceed to the editor." msgstr "Przejdź do edytora." -#: templates/catalogue/image_list.html:7 +#: templates/catalogue/image_list.html:8 msgid "Image list" msgstr "Lista obrazów" -#: templates/catalogue/image_short.html:4 +#: templates/catalogue/image_short.html:6 msgid "Image settings" msgstr "Ustawienia obrazu" -#: templates/catalogue/image_table.html:19 -#: templates/catalogue/book_list/book_list.html:27 +#: templates/catalogue/image_table.html:23 +#: templates/catalogue/book_list/book_list.html:28 msgid "Search in book titles" msgstr "Szukaj w tytułach książek" -#: templates/catalogue/image_table.html:24 -#: templates/catalogue/book_list/book_list.html:32 +#: templates/catalogue/image_table.html:28 +#: templates/catalogue/book_list/book_list.html:33 msgid "stage" msgstr "etap" -#: templates/catalogue/image_table.html:26 -#: templates/catalogue/image_table.html:37 -#: templates/catalogue/book_list/book_list.html:34 -#: templates/catalogue/book_list/book_list.html:45 -#: templates/catalogue/book_list/book_list.html:66 +#: templates/catalogue/image_table.html:30 +#: templates/catalogue/image_table.html:41 +#: templates/catalogue/image_table.html:60 +#: templates/catalogue/book_list/book_list.html:35 +#: templates/catalogue/book_list/book_list.html:46 +#: templates/catalogue/book_list/book_list.html:67 msgid "none" msgstr "brak" -#: templates/catalogue/image_table.html:35 -#: templates/catalogue/book_list/book_list.html:43 +#: templates/catalogue/image_table.html:39 +#: templates/catalogue/book_list/book_list.html:44 msgid "editor" msgstr "redaktor" -#: templates/catalogue/image_table.html:46 -#: templates/catalogue/book_list/book_list.html:56 +#: templates/catalogue/image_table.html:50 +#: templates/catalogue/book_list/book_list.html:57 msgid "status" msgstr "status" -#: templates/catalogue/image_table.html:63 +#: templates/catalogue/image_table.html:77 #, python-format msgid "%(c)s image" msgid_plural "%(c)s images" @@ -443,10 +446,30 @@ msgstr[0] "%(c)s obraz" msgstr[1] "%(c)s obrazy" msgstr[2] "%(c)s obrazów" -#: templates/catalogue/image_table.html:68 +#: templates/catalogue/image_table.html:82 msgid "No images found." msgstr "Nie znaleziono obrazów." +#: templates/catalogue/image_table.html:88 +#: templates/catalogue/book_list/book_list.html:102 +msgid "Set stage" +msgstr "Ustaw etap" + +#: templates/catalogue/image_table.html:89 +#: templates/catalogue/book_list/book_list.html:103 +msgid "Set user" +msgstr "Przypisz redaktora" + +#: templates/catalogue/image_table.html:91 +#: templates/catalogue/book_list/book_list.html:105 +msgid "Project" +msgstr "Projekt" + +#: templates/catalogue/image_table.html:92 +#: templates/catalogue/book_list/book_list.html:106 +msgid "More users" +msgstr "Więcej użytkowników" + #: templates/catalogue/my_page.html:15 templatetags/catalogue.py:27 msgid "My page" msgstr "Moja strona" @@ -464,29 +487,29 @@ msgstr "Ostatnia aktywność dla:" msgid "PDF file upload" msgstr "Ładowanie pliku PDF" -#: templates/catalogue/user_list.html:6 templates/catalogue/user_list.html:11 +#: templates/catalogue/user_list.html:7 templates/catalogue/user_list.html:12 #: templatetags/catalogue.py:32 msgid "Users" msgstr "Użytkownicy" -#: templates/catalogue/wall.html:29 +#: templates/catalogue/wall.html:30 msgid "not logged in" msgstr "nie zalogowany" -#: templates/catalogue/wall.html:34 +#: templates/catalogue/wall.html:35 msgid "No activity recorded." msgstr "Nie zanotowano aktywności." -#: templates/catalogue/book_list/book.html:7 -#: templates/catalogue/book_list/book.html:28 +#: templates/catalogue/book_list/book.html:8 +#: templates/catalogue/book_list/book.html:29 msgid "Book settings" msgstr "Ustawienia książki" -#: templates/catalogue/book_list/book_list.html:22 +#: templates/catalogue/book_list/book_list.html:23 msgid "Show hidden books" msgstr "Pokaż ukryte książki" -#: templates/catalogue/book_list/book_list.html:90 +#: templates/catalogue/book_list/book_list.html:91 #, python-format msgid "%(c)s book" msgid_plural "%(c)s books" @@ -494,34 +517,10 @@ msgstr[0] "%(c)s książka" msgstr[1] "%(c)s książki" msgstr[2] "%(c)s książek" -#: templates/catalogue/book_list/book_list.html:95 +#: templates/catalogue/book_list/book_list.html:96 msgid "No books found." msgstr "Nie znaleziono książek." -#: templates/catalogue/book_list/book_list.html:101 -msgid "Set stage" -msgstr "Ustaw etap" - -#: templates/catalogue/book_list/book_list.html:102 -msgid "Set user" -msgstr "Przypisz redaktora" - -#: templates/catalogue/book_list/book_list.html:104 -msgid "Project" -msgstr "Projekt" - -#: templates/catalogue/book_list/book_list.html:105 -msgid "Mark publishable" -msgstr "Oznacz do publikacji" - -#: templates/catalogue/book_list/book_list.html:106 -msgid "Mark not publishable" -msgstr "Odznacz do publikacji" - -#: templates/catalogue/book_list/book_list.html:107 -msgid "Other user" -msgstr "Inny użytkownik" - #: templatetags/book_list.py:84 templatetags/book_list.py:152 msgid "publishable" msgstr "do publikacji" @@ -558,18 +557,27 @@ msgstr "Dodaj" msgid "Covers" msgstr "Okładki" -#: templatetags/wall.py:49 +#: templatetags/wall.py:49 templatetags/wall.py:78 msgid "Related edit" msgstr "Powiązana zmiana" -#: templatetags/wall.py:51 +#: templatetags/wall.py:51 templatetags/wall.py:80 msgid "Edit" msgstr "Zmiana" -#: templatetags/wall.py:99 +#: templatetags/wall.py:150 msgid "Comment" msgstr "Komentarz" +#~ msgid "Mark publishable" +#~ msgstr "Oznacz do publikacji" + +#~ msgid "Mark not publishable" +#~ msgstr "Odznacz do publikacji" + +#~ msgid "Other user" +#~ msgstr "Inny użytkownik" + #~ msgid "Admin" #~ msgstr "Administracja" diff --git a/apps/catalogue/migrations/0013_auto__add_field_image_project.py b/apps/catalogue/migrations/0013_auto__add_field_image_project.py new file mode 100644 index 00000000..6ae3564f --- /dev/null +++ b/apps/catalogue/migrations/0013_auto__add_field_image_project.py @@ -0,0 +1,196 @@ +# -*- coding: 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 'Image.project' + db.add_column(u'catalogue_image', 'project', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['catalogue.Project'], null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Image.project' + db.delete_column(u'catalogue_image', 'project_id') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'catalogue.book': { + 'Meta': {'ordering': "['title', 'slug']", 'object_name': 'Book'}, + '_new_publishable': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_on_track': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + '_published': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_short_html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + '_single': ('django.db.models.fields.NullBooleanField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + 'dc_cover_image': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['cover.Image']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'dc_slug': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}), + 'gallery': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['catalogue.Book']"}), + 'parent_number': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Project']", 'null': 'True', 'blank': 'True'}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '128'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) + }, + 'catalogue.bookpublishrecord': { + 'Meta': {'ordering': "['-timestamp']", 'object_name': 'BookPublishRecord'}, + 'book': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'publish_log'", 'to': "orm['catalogue.Book']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'catalogue.chunk': { + 'Meta': {'ordering': "['number']", 'unique_together': "[['book', 'number'], ['book', 'slug']]", 'object_name': 'Chunk'}, + '_changed': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_hidden': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_short_html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Book']"}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'created_chunk'", 'null': 'True', 'to': u"orm['auth.User']"}), + 'gallery_start': ('django.db.models.fields.IntegerField', [], {'default': '1', 'null': 'True', 'blank': 'True'}), + 'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['catalogue.ChunkChange']", 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'number': ('django.db.models.fields.IntegerField', [], {}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.ChunkTag']", 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'catalogue.chunkchange': { + 'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'ChunkChange'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", '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'}), + 'data': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'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['catalogue.ChunkChange']"}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['catalogue.ChunkChange']"}), + 'publishable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'change_set'", 'symmetrical': 'False', 'to': "orm['catalogue.ChunkTag']"}), + 'tree': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'change_set'", 'to': "orm['catalogue.Chunk']"}) + }, + 'catalogue.chunkpublishrecord': { + 'Meta': {'object_name': 'ChunkPublishRecord'}, + 'book_record': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.BookPublishRecord']"}), + 'change': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'publish_log'", 'to': "orm['catalogue.ChunkChange']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'catalogue.chunktag': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'ChunkTag'}, + u'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', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) + }, + 'catalogue.image': { + 'Meta': {'ordering': "['title']", 'object_name': 'Image'}, + '_changed': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_new_publishable': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_published': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + '_short_html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'created_image'", 'null': 'True', 'to': u"orm['auth.User']"}), + 'head': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['catalogue.ImageChange']", 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Project']", 'null': 'True', 'blank': 'True'}), + 'public': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}), + 'stage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.ImageTag']", 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) + }, + 'catalogue.imagechange': { + 'Meta': {'ordering': "('created_at',)", 'unique_together': "(['tree', 'revision'],)", 'object_name': 'ImageChange'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", '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'}), + 'data': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'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['catalogue.ImageChange']"}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'blank': 'True', 'to': "orm['catalogue.ImageChange']"}), + 'publishable': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'revision': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'change_set'", 'symmetrical': 'False', 'to': "orm['catalogue.ImageTag']"}), + 'tree': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'change_set'", 'to': "orm['catalogue.Image']"}) + }, + 'catalogue.imagepublishrecord': { + 'Meta': {'ordering': "['-timestamp']", 'object_name': 'ImagePublishRecord'}, + 'change': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'publish_log'", 'to': "orm['catalogue.ImageChange']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'publish_log'", 'to': "orm['catalogue.Image']"}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'catalogue.imagetag': { + 'Meta': {'ordering': "['ordering']", 'object_name': 'ImageTag'}, + u'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', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'}) + }, + 'catalogue.project': { + 'Meta': {'ordering': "['name']", 'object_name': 'Project'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'notes': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}) + }, + u'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'}), + u'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'}) + }, + u'cover.image': { + 'Meta': {'object_name': 'Image'}, + 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'download_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'file': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'license_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'license_url': ('django.db.models.fields.URLField', [], {'max_length': '255', 'blank': 'True'}), + 'source_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + } + } + + complete_apps = ['catalogue'] \ No newline at end of file diff --git a/apps/catalogue/models/image.py b/apps/catalogue/models/image.py index 7b5ce1f2..fffa4b38 100755 --- a/apps/catalogue/models/image.py +++ b/apps/catalogue/models/image.py @@ -9,6 +9,7 @@ from django.db import models from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from catalogue.helpers import cached_in_field +from catalogue.models import Project from catalogue.tasks import refresh_instance from dvcs import models as dvcs_models @@ -21,6 +22,7 @@ class Image(dvcs_models.Document): title = models.CharField(_('title'), max_length=255, blank=True) slug = models.SlugField(_('slug'), unique=True) public = models.BooleanField(_('public'), default=True, db_index=True) + project = models.ForeignKey(Project, null=True, blank=True) # cache _short_html = models.TextField(null=True, blank=True, editable=False) diff --git a/apps/catalogue/templates/catalogue/book_list/book.html b/apps/catalogue/templates/catalogue/book_list/book.html index 5866e6ac..f6a0fcd2 100755 --- a/apps/catalogue/templates/catalogue/book_list/book.html +++ b/apps/catalogue/templates/catalogue/book_list/book.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load username from common_tags %} {% if book.single %} {% with book.0 as chunk %} @@ -13,7 +14,7 @@ {{ chunk.stage }} {% else %}– {% endif %} - {% if chunk.user %}{{ chunk.user.first_name }} {{ chunk.user.last_name }}{% endif %} + {% if chunk.user %}{{ chunk.user|username }}{% endif %} {% if chunk.published %}P{% endif %} {% if book.new_publishable %}p{% endif %} diff --git a/apps/catalogue/templates/catalogue/book_list/book_list.html b/apps/catalogue/templates/catalogue/book_list/book_list.html index 8e254363..e238827b 100755 --- a/apps/catalogue/templates/catalogue/book_list/book_list.html +++ b/apps/catalogue/templates/catalogue/book_list/book_list.html @@ -1,5 +1,6 @@ {% load i18n %} {% load pagination_tags %} +{% load username from common_tags %}
@@ -45,7 +46,7 @@ {% endif %}value="-">- {% trans "none" %} - {% for user in users %} + {% endif %}value="{{ user.username }}">{{ user|username }} ({{ user.count }}) {% endfor %} {% else %} @@ -99,17 +100,15 @@ {% csrf_token %} - + - - - +
diff --git a/apps/catalogue/templates/catalogue/book_list/chunk.html b/apps/catalogue/templates/catalogue/book_list/chunk.html index 7bdf3aa9..0d218954 100755 --- a/apps/catalogue/templates/catalogue/book_list/chunk.html +++ b/apps/catalogue/templates/catalogue/book_list/chunk.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load username from common_tags %} @@ -14,7 +15,7 @@ {% endif %} {% if chunk.user %} - {{ chunk.user.first_name }} {{ chunk.user.last_name }} + {{ chunk.user|username }} {% else %} {% endif %} diff --git a/apps/catalogue/templates/catalogue/image_list.html b/apps/catalogue/templates/catalogue/image_list.html index c6916e8d..a5e35f7e 100755 --- a/apps/catalogue/templates/catalogue/image_list.html +++ b/apps/catalogue/templates/catalogue/image_list.html @@ -2,11 +2,20 @@ {% load i18n %} {% load catalogue book_list %} +{% load compressed %} {% block titleextra %}{% trans "Image list" %}{% endblock %} +{% block add_js %} +{% compressed_js 'book_list' %} +{% endblock %} + +{% block add_css %} +{% compressed_css 'book_list' %} +{% endblock %} + {% block content %} {% image_list %} diff --git a/apps/catalogue/templates/catalogue/image_short.html b/apps/catalogue/templates/catalogue/image_short.html index e64733b6..c7ff77b7 100755 --- a/apps/catalogue/templates/catalogue/image_short.html +++ b/apps/catalogue/templates/catalogue/image_short.html @@ -1,6 +1,8 @@ {% load i18n %} +{% load username from common_tags %} + [B] @@ -9,10 +11,11 @@ {{ image.stage }} {% else %}– {% endif %} - {% if image.user %}{{ image.user.first_name }} {{ image.user.last_name }}{% endif %} + {% if image.user %}{{ image.user|username }}{% endif %} {% if image.published %}P{% endif %} {% if image.new_publishable %}p{% endif %} {% if image.changed %}+{% endif %} + {{ image.project.name }} diff --git a/apps/catalogue/templates/catalogue/image_table.html b/apps/catalogue/templates/catalogue/image_table.html index b152946a..e6caedda 100755 --- a/apps/catalogue/templates/catalogue/image_table.html +++ b/apps/catalogue/templates/catalogue/image_table.html @@ -1,5 +1,7 @@ {% load i18n %} {% load pagination_tags %} +{% load username from common_tags %} +
@@ -9,10 +11,12 @@ {% endif %} +
+ {% endif %} @@ -50,6 +54,16 @@ {% endfor %} + + {% with cnt=objects|length %} @@ -58,7 +72,7 @@ {% for item in objects %} {{ item.short_html|safe }} {% endfor %} - @@ -67,3 +81,20 @@ {% if not objects %}

{% trans "No images found." %}

{% endif %} + + +{% csrf_token %} + + + + + + + + + diff --git a/apps/catalogue/templates/catalogue/user_list.html b/apps/catalogue/templates/catalogue/user_list.html index 26434053..460a38b9 100755 --- a/apps/catalogue/templates/catalogue/user_list.html +++ b/apps/catalogue/templates/catalogue/user_list.html @@ -1,6 +1,7 @@ {% extends "catalogue/base.html" %} {% load i18n %} +{% load username from common_tags %} {% block titleextra %}{% trans "Users" %}{% endblock %} @@ -14,7 +15,7 @@ {% for user in users %}
  • {{ forloop.counter }}. - {{ user.first_name }} {{ user.last_name }} + {{ user|username }} ({{ user.count }})
  • {% endfor %} diff --git a/apps/catalogue/templates/catalogue/wall.html b/apps/catalogue/templates/catalogue/wall.html index d7f6c9e6..64830799 100755 --- a/apps/catalogue/templates/catalogue/wall.html +++ b/apps/catalogue/templates/catalogue/wall.html @@ -1,6 +1,7 @@ {% load i18n %} {% load gravatar %} {% load email %} +{% load username from common_tags %}
      {% for item in wall %} @@ -19,7 +20,7 @@
      {% trans "user" %}: {% if item.user %} - {{ item.user.first_name }} {{ item.user.last_name }} + {{ item.user|username }} <{{ item.user.email|email_link }}> {% else %} {{ item.user_name }} diff --git a/apps/catalogue/templatetags/book_list.py b/apps/catalogue/templatetags/book_list.py index 1357c321..9ac996b8 100755 --- a/apps/catalogue/templatetags/book_list.py +++ b/apps/catalogue/templatetags/book_list.py @@ -175,6 +175,7 @@ def image_list_filter(request, **kwargs): images = foreign_filter(images, arg_or_GET('user'), 'user', User, 'username') images = foreign_filter(images, arg_or_GET('stage'), 'stage', Image.tag_model, 'slug') images = search_filter(images, arg_or_GET('title'), ['title', 'title']) + images = foreign_filter(images, arg_or_GET('project'), 'project', Project, 'pk') return images @@ -187,9 +188,14 @@ def image_list(context, user=None): new_context = {"viewed_user": user} else: filters = {} - new_context = {"users": User.objects.annotate( + new_context = { + "users": User.objects.annotate( count=Count('image')).filter(count__gt=0).order_by( - '-count', 'last_name', 'first_name')} + '-count', 'last_name', 'first_name'), + "other_users": User.objects.annotate( + count=Count('image')).filter(count=0).order_by( + 'last_name', 'first_name'), + } new_context.update({ "filters": True, @@ -197,6 +203,7 @@ def image_list(context, user=None): "objects": image_list_filter(request, **filters), "stages": Image.tag_model.objects.all(), "states": _image_states_options, + "projects": Project.objects.all(), }) return new_context diff --git a/apps/catalogue/templatetags/common_tags.py b/apps/catalogue/templatetags/common_tags.py index ccaf03bf..6baf4e51 100755 --- a/apps/catalogue/templatetags/common_tags.py +++ b/apps/catalogue/templatetags/common_tags.py @@ -5,3 +5,7 @@ register = template.Library() @register.filter def build_absolute_uri(uri, request): return request.build_absolute_uri(uri) + +@register.filter +def username(user): + return ("%s %s" % (user.first_name, user.last_name)).lstrip() or user.username diff --git a/apps/catalogue/templatetags/wall.py b/apps/catalogue/templatetags/wall.py index 28671fb7..e12a313d 100755 --- a/apps/catalogue/templatetags/wall.py +++ b/apps/catalogue/templatetags/wall.py @@ -7,7 +7,7 @@ from django.contrib.comments.models import Comment from django import template from django.utils.translation import ugettext as _ -from catalogue.models import Chunk, BookPublishRecord +from catalogue.models import Chunk, BookPublishRecord, Image, ImagePublishRecord register = template.Library() @@ -60,6 +60,36 @@ def changes_wall(user=None, max_len=None, day=None): yield w +def image_changes_wall(user=None, max_len=None, day=None): + qs = Image.change_model.objects.order_by('-created_at') + qs = qs.select_related('author', 'tree', 'tree__title') + if user is not None: + qs = qs.filter(Q(author=user) | Q(tree__user=user)) + if max_len is not None: + qs = qs[:max_len] + if day is not None: + next_day = day + timedelta(1) + qs = qs.filter(created_at__gte=day, created_at__lt=next_day) + for item in qs: + tag = 'stage' if item.tags.count() else 'change' + image = item.tree + w = WallItem(tag) + if user and item.author != user: + w.header = _('Related edit') + else: + w.header = _('Edit') + w.title = image.title + w.summary = item.description + w.url = reverse('wiki_img_editor', + args=[image.slug]) + '?diff=%d' % item.revision + w.timestamp = item.created_at + w.user = item.author + w.user_name = item.author_name + w.email = item.author_email + yield w + + + # TODO: marked for publishing @@ -84,6 +114,27 @@ def published_wall(user=None, max_len=None, day=None): yield w +def image_published_wall(user=None, max_len=None, day=None): + qs = ImagePublishRecord.objects.select_related('image__title') + if user: + # TODO: published my book + qs = qs.filter(Q(user=user)) + if max_len is not None: + qs = qs[:max_len] + if day is not None: + next_day = day + timedelta(1) + qs = qs.filter(timestamp__gte=day, timestamp__lt=next_day) + for item in qs: + w = WallItem('publish') + w.header = _('Publication') + w.title = item.book.title + w.timestamp = item.timestamp + w.url = item.book.get_absolute_url() + w.user = item.user + w.email = item.user.email + yield w + + def comments_wall(user=None, max_len=None, day=None): qs = Comment.objects.filter(is_public=True).select_related().order_by('-submit_date') if user: @@ -140,6 +191,8 @@ def wall(context, user=None, max_len=100): "wall": big_wall([ changes_wall(user, max_len), published_wall(user, max_len), + image_changes_wall(user, max_len), + image_published_wall(user, max_len), comments_wall(user, max_len), ], max_len)} @@ -151,5 +204,7 @@ def day_wall(context, day): "wall": big_wall([ changes_wall(day=day), published_wall(day=day), + image_changes_wall(day=day), + image_published_wall(day=day), comments_wall(day=day), ])} diff --git a/apps/catalogue/urls.py b/apps/catalogue/urls.py index 3627bf04..908144f1 100644 --- a/apps/catalogue/urls.py +++ b/apps/catalogue/urls.py @@ -50,6 +50,8 @@ urlpatterns = patterns('catalogue.views', 'book_append', name="catalogue_book_append"), url(r'^chunk_mass_edit', 'chunk_mass_edit', name='catalogue_chunk_mass_edit'), + url(r'^image_mass_edit', + 'image_mass_edit', name='catalogue_image_mass_edit'), url(r'^track/(?P[^/]*)/$', PublishTrackFeed()), ) diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 01e4d1fa..237e4a70 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -426,62 +426,86 @@ def chunk_edit(request, slug, chunk): @transaction.commit_on_success @login_required +@require_POST def chunk_mass_edit(request): - if request.method == 'POST': - ids = map(int, filter(lambda i: i.strip()!='', request.POST.get('ids').split(','))) - chunks = map(lambda i: Chunk.objects.get(id=i), ids) - - stage = request.POST.get('stage') - if stage: - try: - stage = Chunk.tag_model.objects.get(slug=stage) - except Chunk.DoesNotExist, e: - stage = None - - for c in chunks: c.stage = stage - - username = request.POST.get('user') - logger.info("username: %s" % username) - logger.info(request.POST) - if username: - try: - user = User.objects.get(username=username) - except User.DoesNotExist, e: - user = None - - for c in chunks: c.user = user - - status = request.POST.get('status') - if status: - books_affected = set() - for c in chunks: - if status == 'publish': - c.head.publishable = True - c.head.save() - elif status == 'unpublish': - c.head.publishable = False - c.head.save() - c.touch() # cache - books_affected.add(c.book) - for b in books_affected: - b.touch() # cache - - project_id = request.POST.get('project') - if project_id: - try: - project = Project.objects.get(pk=int(project_id)) - except (Project.DoesNotExist, ValueError), e: - project = None - for c in chunks: - book = c.book - book.project = project - book.save() - - for c in chunks: c.save() - - return HttpResponse("", content_type="text/plain") - else: - raise Http404 + ids = map(int, filter(lambda i: i.strip()!='', request.POST.get('ids').split(','))) + chunks = map(lambda i: Chunk.objects.get(id=i), ids) + + stage = request.POST.get('stage') + if stage: + try: + stage = Chunk.tag_model.objects.get(slug=stage) + except Chunk.DoesNotExist, e: + stage = None + + for c in chunks: c.stage = stage + + username = request.POST.get('user') + logger.info("username: %s" % username) + logger.info(request.POST) + if username: + try: + user = User.objects.get(username=username) + except User.DoesNotExist, e: + user = None + + for c in chunks: c.user = user + + project_id = request.POST.get('project') + if project_id: + try: + project = Project.objects.get(pk=int(project_id)) + except (Project.DoesNotExist, ValueError), e: + project = None + for c in chunks: + book = c.book + book.project = project + book.save() + + for c in chunks: c.save() + + return HttpResponse("", content_type="text/plain") + + +@transaction.commit_on_success +@login_required +@require_POST +def image_mass_edit(request): + ids = map(int, filter(lambda i: i.strip()!='', request.POST.get('ids').split(','))) + images = map(lambda i: Image.objects.get(id=i), ids) + + stage = request.POST.get('stage') + if stage: + try: + stage = Image.tag_model.objects.get(slug=stage) + except Image.DoesNotExist, e: + stage = None + + for c in images: c.stage = stage + + username = request.POST.get('user') + logger.info("username: %s" % username) + logger.info(request.POST) + if username: + try: + user = User.objects.get(username=username) + except User.DoesNotExist, e: + user = None + + for c in images: c.user = user + + project_id = request.POST.get('project') + if project_id: + try: + project = Project.objects.get(pk=int(project_id)) + except (Project.DoesNotExist, ValueError), e: + project = None + for c in images: + c.project = project + + for c in images: c.save() + + return HttpResponse("", content_type="text/plain") @permission_required('catalogue.change_book') diff --git a/redakcja/static/js/catalogue/book_list.js b/redakcja/static/js/catalogue/book_list.js index 9dd1e413..9d2511d4 100644 --- a/redakcja/static/js/catalogue/book_list.js +++ b/redakcja/static/js/catalogue/book_list.js @@ -1,108 +1,96 @@ (function($) { $(function() { - // clicking on book checks chunks, too - $("input[name=select_book]").change(function(ev) { - $book = $(this); - $book.closest("table").find("input[name=select_chunk][data-book-id=" + $book.val() + "]").attr("checked", $book.is(':checked')); - }); - // initialize context menu - - var get_ids = function() { - return $.map($("input[name=select_chunk]:checked"), function(ele, idx) { - return ele.value; - }).concat( - $.map($("input[name=select_book][data-chunk-id!=]:checked"), function(ele, idx) { - return $(ele).attr("data-chunk-id"); - })).join(); - }; - - - var set_field = function(key, ops) { - var fds = {} - fds.stage = ""; - fds.user = ""; - fds.status = ""; - - if (key == "publish" || key == "unpublish") { - fds["status"] = key; - } else { - var kp = key.split('_'); - var field = kp[0]; - var idx = parseInt(kp[1]); + // clicking on book checks chunks, too + $("input[name=select_book]").change(function(ev) { + $book = $(this); + $book.closest("table").find("input[name=select_chunk][data-book-id=" + $book.val() + "]").attr("checked", $book.is(':checked')); + }); - var target_field = field; - if (field == 'other-user') - target_field = 'user'; + // initialize context menu - fds[target_field] = $("select[name="+field+"] option[value!=]").eq(idx).val(); - } - /* fill in the form */ - $("#chunk_mass_edit [name=ids]").val(get_ids()); - for (var fn in fds) { - $("#chunk_mass_edit [name="+fn+"]").val(fds[fn]); - } + var get_ids = function() { + return $.map($("input[name=select_chunk]:checked"), function(ele, idx) { + return ele.value; + }).concat( + $.map($("input[name=select_book][data-chunk-id!=]:checked"), function(ele, idx) { + return $(ele).attr("data-chunk-id"); + })).join(); + }; - $.post($("#chunk_mass_edit").attr("action"), - $("#chunk_mass_edit").serialize(), - function(data, status) { - location.reload(true); - } - ); + var get_callback = function(form_field_name) { + var $form = $("#chunk_mass_edit"); + var $field = $("[name=" + form_field_name + "]", $form); + var $ids_field = $("[name=ids]").val(get_ids()); + var usable_callback = function(value) { + $field.val(value); + $ids_field.val(get_ids()); + $.post($form.attr("action"), + $form.serialize(), + function(data, status) { + location.reload(true); + } + ); return true; - - - }; - - var get_items = function(field) { - var d = {}; - $.each($("select[name="+field+"] option[value!=]"), - function(idx, ele) { - d[field+"_"+idx] = { name: $(ele).text() }; - }); - return d; }; + return usable_callback; + }; + var get_items = function(field, callback) { + var d = {}; + $.each($("select[name="+field+"] option[value!=]"), + function(idx, ele) { + d[field + "_" + idx] = { + name: $(ele).text(), + callback: function() {callback($(ele).attr('value'));} + }; + }); + return d; + }; - $.contextMenu({ - selector: '#file-list', - items: { - "stage": { - name: $("label[for=mass_edit_stage]").text(), - items: get_items("stage"), - icon: "clock", - }, - "user": { - name: $("label[for=mass_edit_user]").text(), - items: (function() { - var active_users = get_items("user"); - active_users['other'] = { - name: $("label[for=mass_edit_other]").text(), - items: get_items("other-user"), - }; - return active_users; - })(), - icon: "user", - }, - "publish": { - name: $("label[for=mass_edit_publish]").text(), - icon: "ok", - }, - "project" :{ - name: $("label[for=mass_edit_project]").text(), - items: get_items("project"), + var user_callback = get_callback('user'); + var users = [ + get_items("user", user_callback), + {sep: '----'}, + get_items("other-user", user_callback) + ]; + var current_user_items = user_items = {}; + var i = 0; + var more_label = $("label[for=mass_edit_more_users]").text(); + for (user_table in users) { + for (user in users[user_table]) { + if (i && i % 20 == 0) { + var more_items = {}; + current_user_items['more'] = { + name: more_label, + items: more_items + }; + current_user_items = more_items; + } + current_user_items[user] = users[user_table][user]; + i += 1; + } + } + $.contextMenu({ + selector: '#file-list', + items: { + stage: { + name: $("label[for=mass_edit_stage]").text(), + items: get_items("stage", get_callback('stage')), + icon: "clock", + }, + user: { + name: $("label[for=mass_edit_user]").text(), + items: user_items, + icon: "user", }, - "publish": { - name: $("label[for=mass_edit_publish]").text(), - icon: "ok", + project: { + name: $("label[for=mass_edit_project]").text(), + items: get_items("project", get_callback('project')), }, - "unpublish": { - name: $("label[for=mass_edit_unpublish]").text(), - icon: "stop", - }, - }, - callback: set_field, - }); - + }, + }); + + }); })(jQuery); diff --git a/redakcja/static/js/wiki_img/wikiapi.js b/redakcja/static/js/wiki_img/wikiapi.js index 81cd3162..cac7e485 100644 --- a/redakcja/static/js/wiki_img/wikiapi.js +++ b/redakcja/static/js/wiki_img/wikiapi.js @@ -49,6 +49,18 @@ this.revision = $("*[data-key='revision']", meta).text(); this.readonly = !!$("*[data-key='readonly']", meta).text(); + var diff = $("*[data-key='diff']", meta).text(); + if (diff) { + 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.text = null; this.has_local_changes = false; this._lock = -1; -- 2.20.1
    @@ -37,7 +41,7 @@ {% endif %}value="-">- {% trans "none" %} - {% for user in users %} + {% endif %}value="{{ user.username }}">{{ user|username }} ({{ user.count }}) {% endfor %}
    +
    {% paginate %} {% blocktrans count c=cnt %}{{c}} image{% plural %}{{c}} images{% endblocktrans %}