Add projects for images and port mass_edit.
authorRadek Czajka <radekczajka@nowoczesnapolska.org.pl>
Thu, 27 Mar 2014 12:20:29 +0000 (13:20 +0100)
committerRadek Czajka <radekczajka@nowoczesnapolska.org.pl>
Thu, 27 Mar 2014 12:20:29 +0000 (13:20 +0100)
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.

20 files changed:
apps/catalogue/forms.py
apps/catalogue/locale/pl/LC_MESSAGES/django.mo
apps/catalogue/locale/pl/LC_MESSAGES/django.po
apps/catalogue/migrations/0013_auto__add_field_image_project.py [new file with mode: 0644]
apps/catalogue/models/image.py
apps/catalogue/templates/catalogue/book_list/book.html
apps/catalogue/templates/catalogue/book_list/book_list.html
apps/catalogue/templates/catalogue/book_list/chunk.html
apps/catalogue/templates/catalogue/image_list.html
apps/catalogue/templates/catalogue/image_short.html
apps/catalogue/templates/catalogue/image_table.html
apps/catalogue/templates/catalogue/user_list.html
apps/catalogue/templates/catalogue/wall.html
apps/catalogue/templatetags/book_list.py
apps/catalogue/templatetags/common_tags.py
apps/catalogue/templatetags/wall.py
apps/catalogue/urls.py
apps/catalogue/views.py
redakcja/static/js/catalogue/book_list.js
redakcja/static/js/wiki_img/wikiapi.js

index 83b1652..a2ae86a 100644 (file)
@@ -175,7 +175,7 @@ class ImageForm(forms.ModelForm):
 
 
 class ReadonlyImageForm(ImageForm):
 
 
 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)
 
     def __init__(self, *args, **kwargs):
         ret = super(ReadonlyImageForm, self).__init__(*args, **kwargs)
index 64f78b4..17689b8 100644 (file)
Binary files a/apps/catalogue/locale/pl/LC_MESSAGES/django.mo and b/apps/catalogue/locale/pl/LC_MESSAGES/django.mo differ
index d98440f..64ddd9f 100644 (file)
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Platforma Redakcyjna\n"
 "Report-Msgid-Bugs-To: \n"
 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 <radoslaw.czajka@nowoczesnapolska.org.pl>\n"
 "Language-Team: Fundacja Nowoczesna Polska <fundacja@nowoczesnapolska.org."
 "pl>\n"
 "Last-Translator: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>\n"
 "Language-Team: Fundacja Nowoczesna Polska <fundacja@nowoczesnapolska.org."
 "pl>\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."
 
 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"
 
 msgid "books"
 msgstr "książki"
 
-#: views.py:554
+#: views.py:578
 msgid "scan gallery"
 msgstr "galeria skanów"
 
 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ł"
 
 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"
 
 msgid "slug"
 msgstr "slug"
 
-#: models/book.py:30 models/image.py:23
+#: models/book.py:30 models/image.py:24
 msgid "public"
 msgstr "publiczna"
 
 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."
 
 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"
 
 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."
 
 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"
 
 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"
 
 msgid "rdf:about is not"
 msgstr "rdf:about jest różny od"
 
@@ -137,15 +137,15 @@ msgstr "część"
 msgid "chunks"
 msgstr "części"
 
 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"
 
 msgid "image"
 msgstr "obraz"
 
-#: models/image.py:35
+#: models/image.py:37
 msgid "images"
 msgstr "obrazy"
 
 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."
 
 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"
 
 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"
 
 msgid "project"
 msgstr "projekt"
 
@@ -170,7 +171,7 @@ msgid "time"
 msgstr "czas"
 
 #: models/publish_log.py:19 models/publish_log.py:47
 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"
 
 msgid "user"
 msgstr "użytkownik"
 
@@ -236,7 +237,8 @@ msgid "Chunks"
 msgstr "Części"
 
 #: templates/catalogue/book_detail.html:49
 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"
 
 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
 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"
 
 msgid "Chunk settings"
 msgstr "Ustawienia części"
 
@@ -399,43 +401,44 @@ msgstr "Edytor"
 msgid "Proceed to the editor."
 msgstr "Przejdź do edytora."
 
 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"
 
 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"
 
 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"
 
 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"
 
 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"
 
 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"
 
 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"
 
 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"
 #, 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"
 
 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."
 
 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"
 #: 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"
 
 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"
 
 #: 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"
 
 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."
 
 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"
 
 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"
 
 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"
 #, 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"
 
 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."
 
 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"
 #: 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"
 
 msgid "Covers"
 msgstr "Okładki"
 
-#: templatetags/wall.py:49
+#: templatetags/wall.py:49 templatetags/wall.py:78
 msgid "Related edit"
 msgstr "Powiązana zmiana"
 
 msgid "Related edit"
 msgstr "Powiązana zmiana"
 
-#: templatetags/wall.py:51
+#: templatetags/wall.py:51 templatetags/wall.py:80
 msgid "Edit"
 msgstr "Zmiana"
 
 msgid "Edit"
 msgstr "Zmiana"
 
-#: templatetags/wall.py:99
+#: templatetags/wall.py:150
 msgid "Comment"
 msgstr "Komentarz"
 
 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"
 
 #~ 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 (file)
index 0000000..6ae3564
--- /dev/null
@@ -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
index 7b5ce1f..fffa4b3 100755 (executable)
@@ -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 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
 
 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)
     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)
 
     # cache
     _short_html = models.TextField(null=True, blank=True, editable=False)
index 5866e6a..f6a0fcd 100755 (executable)
@@ -1,4 +1,5 @@
 {% load i18n %}
 {% load i18n %}
+{% load username from common_tags %}
 
 {% if book.single %}
     {% with book.0 as chunk %}
 
 {% if book.single %}
     {% with book.0 as chunk %}
@@ -13,7 +14,7 @@
             {{ chunk.stage }}
         {% else %}–
         {% endif %}</td>
             {{ chunk.stage }}
         {% else %}–
         {% endif %}</td>
-        <td class='user-column'>{% if chunk.user %}<a href="{% url 'catalogue_user' chunk.user.username %}">{{ chunk.user.first_name }} {{ chunk.user.last_name }}</a>{% endif %}</td>
+        <td class='user-column'>{% if chunk.user %}<a href="{% url 'catalogue_user' chunk.user.username %}">{{ chunk.user|username }}</a>{% endif %}</td>
         <td>
             {% if chunk.published %}P{% endif %}
             {% if book.new_publishable %}p{% endif %}
         <td>
             {% if chunk.published %}P{% endif %}
             {% if book.new_publishable %}p{% endif %}
index 8e25436..e238827 100755 (executable)
@@ -1,5 +1,6 @@
 {% load i18n %}
 {% load pagination_tags %}
 {% load i18n %}
 {% load pagination_tags %}
+{% load username from common_tags %}
 
 
 <form name='filter' action='{{ request.path }}'>
 
 
 <form name='filter' action='{{ request.path }}'>
@@ -45,7 +46,7 @@
                         {% endif %}value="-">- {% trans "none" %} -</option>
                 {% for user in users %}
                     <option {% if request.GET.user == user.username %}selected="selected"
                         {% endif %}value="-">- {% trans "none" %} -</option>
                 {% for user in users %}
                     <option {% if request.GET.user == user.username %}selected="selected"
-                        {% endif %}value="{{ user.username }}">{{ user.first_name }} {{ user.last_name }} ({{ user.count }})</option>
+                        {% endif %}value="{{ user.username }}">{{ user|username }} ({{ user.count }})</option>
                 {% endfor %}
             </select></th>
         {% else %}
                 {% endfor %}
             </select></th>
         {% else %}
 {% csrf_token %}
 <input type="hidden" name="ids" />
 <label for="mass_edit_stage">{% trans "Set stage" %}</label><input type="hidden" name="stage" id="mass_edit_stage"/>
 {% csrf_token %}
 <input type="hidden" name="ids" />
 <label for="mass_edit_stage">{% trans "Set stage" %}</label><input type="hidden" name="stage" id="mass_edit_stage"/>
-<label for="mass_edit_user">{% trans "Set user" %}</label><input type="hidden" name="user" id="mass_edit_stage" />
+<label for="mass_edit_user">{% trans "Set user" %}</label><input type="hidden" name="user" id="mass_edit_user" />
 <input type="hidden" name="status" />
 <label for="mass_edit_project">{% trans "Project" %}</label><input type="hidden" name="project" id="mass_edit_project" />
 <input type="hidden" name="status" />
 <label for="mass_edit_project">{% trans "Project" %}</label><input type="hidden" name="project" id="mass_edit_project" />
-<label for="mass_edit_publish">{% trans "Mark publishable" %}</label>
-<label for="mass_edit_unpublish">{% trans "Mark not publishable" %}</label>
-<label for="mass_edit_other">{% trans "Other user" %}</label>
+<label for="mass_edit_more_users">{% trans "More users" %}</label>
 </form>
 
 <select name="other-user" style="display:none;">
   {% for user in other_users %}
   <option {% if request.GET.user == user.username %}selected="selected"
 </form>
 
 <select name="other-user" style="display:none;">
   {% for user in other_users %}
   <option {% if request.GET.user == user.username %}selected="selected"
-          {% endif %}value="{{ user.username }}">{{ user.first_name }} {{ user.last_name }} ({{ user.count }})</option>
+          {% endif %}value="{{ user.username }}">{{ user|username }} ({{ user.count }})</option>
   {% endfor %}
 </select>
   {% endfor %}
 </select>
index 7bdf3aa..0d21895 100755 (executable)
@@ -1,4 +1,5 @@
 {% load i18n %}
 {% load i18n %}
+{% load username from common_tags %}
 
 <tr>
     <td><input type="checkbox" name="select_chunk" value="{{chunk.id}}" data-book-id="{{chunk.book.id}}" /></td>
 
 <tr>
     <td><input type="checkbox" name="select_chunk" value="{{chunk.id}}" data-book-id="{{chunk.book.id}}" /></td>
@@ -14,7 +15,7 @@
         {% endif %}</td>
         <td class='user-column'>{% if chunk.user %}
             <a href="{% url 'catalogue_user' chunk.user.username %}">
         {% endif %}</td>
         <td class='user-column'>{% if chunk.user %}
             <a href="{% url 'catalogue_user' chunk.user.username %}">
-                {{ chunk.user.first_name }} {{ chunk.user.last_name }}
+                {{ chunk.user|username }}
             </a>{% else %}
             
             {% endif %}</td>
             </a>{% else %}
             
             {% endif %}</td>
index c6916e8..a5e35f7 100755 (executable)
@@ -2,11 +2,20 @@
 
 {% load i18n %}
 {% load catalogue book_list %}
 
 {% load i18n %}
 {% load catalogue book_list %}
+{% load compressed %}
 
 
 {% block titleextra %}{% trans "Image list" %}{% endblock %}
 
 
 
 
 {% 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 %}
 
 {% block content %}
     {% image_list %}
index e64733b..c7ff77b 100755 (executable)
@@ -1,6 +1,8 @@
 {% load i18n %}
 {% load i18n %}
+{% load username from common_tags %}
 
 <tr>
 
 <tr>
+    <td><input type="checkbox" name="select_chunk" value="{{image.id}}"/></td>
     <td><a href="{% url 'catalogue_image' image.slug %}" title='{% trans "Image settings" %}'>[B]</a></td>
     <td><a target="_blank"
                 href="{% url 'wiki_img_editor' image.slug %}">
     <td><a href="{% url 'catalogue_image' image.slug %}" title='{% trans "Image settings" %}'>[B]</a></td>
     <td><a target="_blank"
                 href="{% url 'wiki_img_editor' image.slug %}">
         {{ image.stage }}
     {% else %}–
     {% endif %}</td>
         {{ image.stage }}
     {% else %}–
     {% endif %}</td>
-    <td class='user-column'>{% if image.user %}<a href="{% url 'catalogue_user' image.user.username %}">{{ image.user.first_name }} {{ image.user.last_name }}</a>{% endif %}</td>
+    <td class='user-column'>{% if image.user %}<a href="{% url 'catalogue_user' image.user.username %}">{{ image.user|username }}</a>{% endif %}</td>
     <td>
         {% if image.published %}P{% endif %}
         {% if image.new_publishable %}p{% endif %}
         {% if image.changed %}+{% endif %}
     </td>
     <td>
         {% if image.published %}P{% endif %}
         {% if image.new_publishable %}p{% endif %}
         {% if image.changed %}+{% endif %}
     </td>
+    <td>{{ image.project.name }}</td>
 </tr>
 </tr>
index b152946..e6caedd 100755 (executable)
@@ -1,5 +1,7 @@
 {% load i18n %}
 {% load pagination_tags %}
 {% load i18n %}
 {% load pagination_tags %}
+{% load username from common_tags %}
+
 
 
 <form name='filter' action='{{ request.path }}'>
 
 
 <form name='filter' action='{{ request.path }}'>
     <input type='hidden' name="user" value="{{ request.GET.user }}" />
 {% endif %}
 <input type='hidden' name="status" value="{{ request.GET.status }}" />
     <input type='hidden' name="user" value="{{ request.GET.user }}" />
 {% endif %}
 <input type='hidden' name="status" value="{{ request.GET.status }}" />
+<input type='hidden' name="project" value="{{ request.GET.project }}" />
 </form>
 
 <table id="file-list"{% if viewed_user %} class="book-list-user"{% endif %}>
     <thead><tr>
 </form>
 
 <table id="file-list"{% if viewed_user %} class="book-list-user"{% endif %}>
     <thead><tr>
+        <th></th>
         <th></th>
         <th class='book-search-column'>
             <form>
         <th></th>
         <th class='book-search-column'>
             <form>
@@ -37,7 +41,7 @@
                         {% endif %}value="-">- {% trans "none" %} -</option>
                 {% for user in users %}
                     <option {% if request.GET.user == user.username %}selected="selected"
                         {% endif %}value="-">- {% trans "none" %} -</option>
                 {% for user in users %}
                     <option {% if request.GET.user == user.username %}selected="selected"
-                        {% endif %}value="{{ user.username }}">{{ user.first_name }} {{ user.last_name }} ({{ user.count }})</option>
+                        {% endif %}value="{{ user.username }}">{{ user|username }} ({{ user.count }})</option>
                 {% endfor %}
             </select></th>
         {% endif %}
                 {% endfor %}
             </select></th>
         {% endif %}
             {% endfor %}
         </select></th>
 
             {% endfor %}
         </select></th>
 
+        <th><select name="project" class="filter">
+            <option value=''>- {% trans "project" %} -</option>
+                <option {% if request.GET.project == '-' %}selected="selected"
+                        {% endif %}value="-">- {% trans "none" %} -</option>
+            {% for project in projects %}
+                <option {% if request.GET.project == project.pk|slugify %}selected="selected"
+                        {% endif %}value='{{ project.pk }}'>{{ project.name }}</option>
+            {% endfor %}
+        </select></th>
+
     </tr></thead>
 
     {% with cnt=objects|length %}
     </tr></thead>
 
     {% with cnt=objects|length %}
@@ -58,7 +72,7 @@
     {% for item in objects %}
         {{ item.short_html|safe }}
     {% endfor %}
     {% for item in objects %}
         {{ item.short_html|safe }}
     {% endfor %}
-    <tr><th class='paginator' colspan="5">
+    <tr><th class='paginator' colspan="6">
         {% paginate %}
         {% blocktrans count c=cnt %}{{c}} image{% plural %}{{c}} images{% endblocktrans %}</th></tr>
     </tbody>
         {% paginate %}
         {% blocktrans count c=cnt %}{{c}} image{% plural %}{{c}} images{% endblocktrans %}</th></tr>
     </tbody>
 {% if not objects %}
     <p>{% trans "No images found." %}</p>
 {% endif %}
 {% if not objects %}
     <p>{% trans "No images found." %}</p>
 {% endif %}
+
+<form id='chunk_mass_edit' action='{% url "catalogue_image_mass_edit" %}' style="display:none;">
+{% csrf_token %}
+<input type="hidden" name="ids" />
+<label for="mass_edit_stage">{% trans "Set stage" %}</label><input type="hidden" name="stage" id="mass_edit_stage"/>
+<label for="mass_edit_user">{% trans "Set user" %}</label><input type="hidden" name="user" id="mass_edit_stage" />
+<input type="hidden" name="status" />
+<label for="mass_edit_project">{% trans "Project" %}</label><input type="hidden" name="project" id="mass_edit_project" />
+<label for="mass_edit_more_users">{% trans "More users" %}</label>
+</form>
+
+<select name="other-user" style="display:none;">
+  {% for user in other_users %}
+  <option {% if request.GET.user == user.username %}selected="selected"
+          {% endif %}value="{{ user.username }}">{{ user|username }} ({{ user.count }})</option>
+  {% endfor %}
+</select>
index 2643405..460a38b 100755 (executable)
@@ -1,6 +1,7 @@
 {% extends "catalogue/base.html" %}
 
 {% load i18n %}
 {% extends "catalogue/base.html" %}
 
 {% load i18n %}
+{% load username from common_tags %}
 
 
 {% block titleextra %}{% trans "Users" %}{% endblock %}
 
 
 {% block titleextra %}{% trans "Users" %}{% endblock %}
@@ -14,7 +15,7 @@
 {% for user in users %}
     <li><a href="{% url 'catalogue_user' user.username %}">
         <span class="chunkno">{{ forloop.counter }}.</span>
 {% for user in users %}
     <li><a href="{% url 'catalogue_user' user.username %}">
         <span class="chunkno">{{ forloop.counter }}.</span>
-        {{ user.first_name }} {{ user.last_name }}</a>
+        {{ user|username }}</a>
         ({{ user.count }})</li>
 {% endfor %}
 </ul>
         ({{ user.count }})</li>
 {% endfor %}
 </ul>
index d7f6c9e..6483079 100755 (executable)
@@ -1,6 +1,7 @@
 {% load i18n %}
 {% load gravatar %}
 {% load email %}
 {% load i18n %}
 {% load gravatar %}
 {% load email %}
+{% load username from common_tags %}
 
 <ul class='wall'>
 {% for item in wall %}
 
 <ul class='wall'>
 {% for item in wall %}
@@ -19,7 +20,7 @@
         <br/><strong>{% trans "user" %}:</strong>
         {% if item.user %}
             <a href="{% url 'catalogue_user' item.user.username %}">
         <br/><strong>{% trans "user" %}:</strong>
         {% if item.user %}
             <a href="{% url 'catalogue_user' item.user.username %}">
-            {{ item.user.first_name }} {{ item.user.last_name }}</a>
+            {{ item.user|username }}</a>
             &lt;{{ item.user.email|email_link }}>
         {% else %}
             {{ item.user_name }}
             &lt;{{ item.user.email|email_link }}>
         {% else %}
             {{ item.user_name }}
index 1357c32..9ac996b 100755 (executable)
@@ -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('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
 
 
     return images
 
 
@@ -187,9 +188,14 @@ def image_list(context, user=None):
         new_context = {"viewed_user": user}
     else:
         filters = {}
         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=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,
 
     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,
         "objects": image_list_filter(request, **filters),
         "stages": Image.tag_model.objects.all(),
         "states": _image_states_options,
+        "projects": Project.objects.all(),
     })
 
     return new_context
     })
 
     return new_context
index ccaf03b..6baf4e5 100755 (executable)
@@ -5,3 +5,7 @@ register = template.Library()
 @register.filter
 def build_absolute_uri(uri, request):
     return request.build_absolute_uri(uri)
 @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
index 28671fb..e12a313 100755 (executable)
@@ -7,7 +7,7 @@ from django.contrib.comments.models import Comment
 from django import template
 from django.utils.translation import ugettext as _
 
 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()
 
 
 register = template.Library()
 
@@ -60,6 +60,36 @@ def changes_wall(user=None, max_len=None, day=None):
         yield w
 
 
         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
 
 
 # TODO: marked for publishing
 
 
@@ -84,6 +114,27 @@ def published_wall(user=None, max_len=None, day=None):
         yield w
 
 
         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:
 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),
         "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)}
 
             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),
         "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),
         ])}
             comments_wall(day=day),
         ])}
index 3627bf0..908144f 100644 (file)
@@ -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'),
         '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<slug>[^/]*)/$', PublishTrackFeed()),
 )
 
     url(r'^track/(?P<slug>[^/]*)/$', PublishTrackFeed()),
 )
index 01e4d1f..237e4a7 100644 (file)
@@ -426,62 +426,86 @@ def chunk_edit(request, slug, chunk):
 
 @transaction.commit_on_success
 @login_required
 
 @transaction.commit_on_success
 @login_required
+@require_POST
 def chunk_mass_edit(request):
 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')
 
 
 @permission_required('catalogue.change_book')
index 9dd1e41..9d2511d 100644 (file)
 (function($) {
     $(function() {
 (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;
             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);
     });
 })(jQuery);
index 81cd316..cac7e48 100644 (file)
                this.revision = $("*[data-key='revision']", meta).text();
                this.readonly = !!$("*[data-key='readonly']", meta).text();
 
                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;
                this.text = null;
                this.has_local_changes = false;
                this._lock = -1;