From: Radek Czajka 
Date: Wed, 8 Aug 2012 13:27:54 +0000 (+0200)
Subject: submit form
X-Git-Url: https://git.mdrn.pl/prawokultury.git/commitdiff_plain/891a1e056e6066b28e000df16d69b21946338a57?ds=inline;hp=-c
submit form
---
891a1e056e6066b28e000df16d69b21946338a57
diff --git a/migdal/forms.py b/migdal/forms.py
new file mode 100755
index 0000000..5a9d5d0
--- /dev/null
+++ b/migdal/forms.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+# This file is part of PrawoKultury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django import forms
+from django.utils.translation import ugettext_lazy as _, get_language
+from migdal.models import Entry
+from migdal.settings import TYPE_SUBMIT
+from slughifi import slughifi
+from django.core.mail import mail_managers
+from django import template
+
+
+def get_submit_form(*args, **kwargs):
+    lang = get_language()
+
+    class SubmitForm(forms.ModelForm):
+        class Meta:
+            model = Entry
+            fields = ['title_%s' % lang, 'lead_%s' % lang,
+                'author', 'author_email', 'categories']
+            required = ['title_%s' % lang]
+
+        def __init__(self, *args, **kwargs):
+            super(SubmitForm, self).__init__(*args, **kwargs)
+            self.fields['title_%s' % lang].required = True
+            self.fields['lead_%s' % lang].required = True
+
+        def clean(self):
+            data = super(SubmitForm, self).clean()
+            data['type'] = TYPE_SUBMIT
+            orig_slug = slughifi(data.get('title_%s' % lang, ''))
+            slug = orig_slug
+            number = 2
+            while Entry.objects.filter(**{'slug_%s' % lang: slug}).exists():
+                slug = "%s-%s" % (orig_slug, number)
+                number += 1
+            data['slug_%s' % lang] = slug
+            self.cleaned_data = data
+            return data
+
+        def save(self, *args, **kwargs):
+            entry = super(SubmitForm, self).save(commit=False)
+            # Something's wrong with markup fields, they choke on None here.
+            for f in 'lead_en', 'lead_pl', 'body_en', 'body_pl':
+                if getattr(entry, f) is None:
+                    setattr(entry, f, '')
+            for f in 'slug_%s' % lang, 'type':
+                setattr(entry, f, self.cleaned_data[f])
+            entry.save()
+            entry = super(SubmitForm, self).save(*args, **kwargs)
+            mail_managers(u"Nowy wpis",
+                template.loader.get_template(
+                    'migdal/mail/manager_new_entry.txt').render(
+                        template.Context({'object': entry})))
+
+    return SubmitForm(*args, **kwargs)
\ No newline at end of file
diff --git a/migdal/helpers.py b/migdal/helpers.py
index 4fec03a..1fdbdd4 100644
--- a/migdal/helpers.py
+++ b/migdal/helpers.py
@@ -12,6 +12,7 @@ from django.utils.translation import get_language, string_concat
 
 
 class EntryType(namedtuple('EntryType', 'db slug commentable on_main')):
+    __slots__ = ()
     def __unicode__(self):
         return unicode(self.slug)
 
diff --git a/migdal/locale/pl/LC_MESSAGES/django.mo b/migdal/locale/pl/LC_MESSAGES/django.mo
index 52cedd2..b461c96 100644
Binary files a/migdal/locale/pl/LC_MESSAGES/django.mo and b/migdal/locale/pl/LC_MESSAGES/django.mo differ
diff --git a/migdal/locale/pl/LC_MESSAGES/django.po b/migdal/locale/pl/LC_MESSAGES/django.po
index 1055e0e..c737385 100644
--- a/migdal/locale/pl/LC_MESSAGES/django.po
+++ b/migdal/locale/pl/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: django-migdal 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-08-07 17:28+0200\n"
-"PO-Revision-Date: 2012-08-07 17:31+0100\n"
+"POT-Creation-Date: 2012-08-08 15:23+0200\n"
+"PO-Revision-Date: 2012-08-08 15:26+0100\n"
 "Last-Translator: Radek Czajka \n"
 "Language-Team: FNP \n"
 "Language: Polish\n"
@@ -27,7 +27,7 @@ msgid "latest"
 msgstr "ostatnie"
 
 #: feeds.py:30
-#: models.py:48
+#: models.py:46
 msgid "entries"
 msgstr "wpisy"
 
@@ -40,66 +40,73 @@ msgid "category"
 msgstr "kategoria"
 
 #: models.py:16
-#: urls.py:32
-#: urls.py:34
+#: urls.py:35
+#: urls.py:37
 msgid "categories"
 msgstr "kategorie"
 
-#: models.py:40
+#: models.py:37
 msgid "author"
 msgstr "autor"
 
-#: models.py:41
+#: models.py:38
 msgid "author email"
 msgstr "e-mail autora"
 
-#: models.py:42
+#: models.py:39
+msgid "Used only to display gravatar and send notifications."
+msgstr "Używany tylko do wyÅwietlenia gravatara i wysyÅania powiadomieÅ."
+
+#: models.py:40
 msgid "image"
 msgstr "obrazek"
 
-#: models.py:43
+#: models.py:41
 msgid "promoted"
 msgstr "promowane"
 
-#: models.py:47
+#: models.py:45
 msgid "entry"
 msgstr "wpis"
 
-#: models.py:72
-#: models.py:78
-msgid "title"
-msgstr "tytuÅ"
-
-#: models.py:73
-#: models.py:79
-msgid "lead"
-msgstr "lead"
-
-#: models.py:80
+#: models.py:68
 msgid "needed"
 msgstr "potrzebne"
 
-#: models.py:81
+#: models.py:69
 msgid "Unneeded"
 msgstr "Niepotrzebne"
 
-#: models.py:81
+#: models.py:69
 msgid "Needed"
 msgstr "Potrzebne"
 
-#: models.py:81
+#: models.py:69
 msgid "Done"
 msgstr "UkoÅczone"
 
-#: models.py:86
+#: models.py:75
+msgid "title"
+msgstr "tytuÅ"
+
+#: models.py:76
+msgid "lead"
+msgstr "lead"
+
+#: models.py:77
+#: models.py:79
+msgid "Use Textile syntax."
+msgstr "WÅÄ
czona skÅadnia Textile."
+
+#: models.py:78
 msgid "body"
 msgstr "treÅÄ"
 
-#: models.py:87
+#: models.py:80
 msgid "published"
 msgstr "opublikowane"
 
-#: models.py:93
+#: models.py:85
 msgid "file"
 msgstr "plik"
 
@@ -115,6 +122,15 @@ msgstr "publikacje"
 msgid "info"
 msgstr "info"
 
+#: urls.py:32
+#: urls.py:33
+msgid "submit"
+msgstr "wyslij"
+
+#: urls.py:33
+msgid "thanks"
+msgstr "dzieki"
+
 #: templates/comments/migdal/entry/preview.html:19
 msgid "Please correct the error below"
 msgid_plural "Please correct the errors below"
@@ -154,6 +170,10 @@ msgstr "Kategoria"
 msgid "Latest news"
 msgstr "Ostatnie newsy"
 
+#: templates/migdal/entry/entry_list.html:21
+msgid "Submit a new story."
+msgstr "PrzyÅlij nowego newsa."
+
 #: templates/migdal/entry/entry_short.html:10
 msgid "read more"
 msgstr "czytaj wiÄcej"
@@ -166,3 +186,21 @@ msgstr[0] "%(c)s komentarz"
 msgstr[1] "%(c)s komentarze"
 msgstr[2] "%(c)s komentarzy"
 
+#: templates/migdal/entry/submit.html:7
+msgid "Submit new story"
+msgstr "PrzyÅlij nowego newsa."
+
+#: templates/migdal/entry/submit_thanks.html:7
+msgid "Thanks for submitting"
+msgstr "DziÄkujemy za zgÅoszenie"
+
+#: templates/migdal/entry/submit_thanks.html:9
+msgid ""
+"\n"
+"Thank you for submitting this new story, it's waiting for moderation.\n"
+"If you provided an email, we'll inform you about changes in it's status\n"
+"and comments.\n"
+msgstr ""
+"\n"
+"DziÄkujemy za przysÅanie nowego newsa, teraz czeka on na moderacjÄ.JeÅli podano adres e-mail, bÄdziemy CiÄ informowali o zmianach statusui komentarzach\n"
+
diff --git a/migdal/migrations/0002_auto__chg_field_entry_slug_pl__chg_field_entry_title_pl__chg_field_ent.py b/migdal/migrations/0002_auto__chg_field_entry_slug_pl__chg_field_entry_title_pl__chg_field_ent.py
new file mode 100644
index 0000000..1caced4
--- /dev/null
+++ b/migdal/migrations/0002_auto__chg_field_entry_slug_pl__chg_field_entry_title_pl__chg_field_ent.py
@@ -0,0 +1,79 @@
+# -*- 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):
+
+        # Changing field 'Entry.slug_pl'
+        db.alter_column('migdal_entry', 'slug_pl', self.gf('django.db.models.fields.SlugField')(max_length=50, unique=True, null=True))
+
+        # Changing field 'Entry.title_pl'
+        db.alter_column('migdal_entry', 'title_pl', self.gf('django.db.models.fields.CharField')(max_length=255, null=True))
+
+        # Changing field 'Entry.lead_pl'
+        db.alter_column('migdal_entry', 'lead_pl', self.gf('markupfield.fields.MarkupField')(null=True, rendered_field=True))
+
+    def backwards(self, orm):
+
+        # Changing field 'Entry.slug_pl'
+        db.alter_column('migdal_entry', 'slug_pl', self.gf('django.db.models.fields.SlugField')(default='', max_length=50, unique=True))
+
+        # Changing field 'Entry.title_pl'
+        db.alter_column('migdal_entry', 'title_pl', self.gf('django.db.models.fields.CharField')(default='', max_length=255))
+
+        # Changing field 'Entry.lead_pl'
+        db.alter_column('migdal_entry', 'lead_pl', self.gf('markupfield.fields.MarkupField')(default='', rendered_field=True))
+
+    models = {
+        'migdal.attachment': {
+            'Meta': {'object_name': 'Attachment'},
+            'entry': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['migdal.Entry']"}),
+            'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'migdal.category': {
+            'Meta': {'object_name': 'Category'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'slug_en': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
+            'slug_pl': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}),
+            'title_en': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64', 'db_index': 'True'}),
+            'title_pl': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64', 'db_index': 'True'})
+        },
+        'migdal.entry': {
+            'Meta': {'ordering': "['-date']", 'object_name': 'Entry'},
+            '_body_en_rendered': ('django.db.models.fields.TextField', [], {}),
+            '_body_pl_rendered': ('django.db.models.fields.TextField', [], {}),
+            '_lead_en_rendered': ('django.db.models.fields.TextField', [], {}),
+            '_lead_pl_rendered': ('django.db.models.fields.TextField', [], {}),
+            'author': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'author_email': ('django.db.models.fields.EmailField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
+            'body_en': ('markupfield.fields.MarkupField', [], {'null': 'True', 'rendered_field': 'True', 'blank': 'True'}),
+            'body_en_markup_type': ('django.db.models.fields.CharField', [], {'default': "'textile_pl'", 'max_length': '30', 'blank': 'True'}),
+            'body_pl': ('markupfield.fields.MarkupField', [], {'null': 'True', 'rendered_field': 'True', 'blank': 'True'}),
+            'body_pl_markup_type': ('django.db.models.fields.CharField', [], {'default': "'textile_pl'", 'max_length': '30', 'blank': 'True'}),
+            'categories': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['migdal.Category']", 'null': 'True', 'blank': 'True'}),
+            'date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'lead_en': ('markupfield.fields.MarkupField', [], {'null': 'True', 'rendered_field': 'True', 'blank': 'True'}),
+            'lead_en_markup_type': ('django.db.models.fields.CharField', [], {'default': "'textile_pl'", 'max_length': '30', 'blank': 'True'}),
+            'lead_pl': ('markupfield.fields.MarkupField', [], {'null': 'True', 'rendered_field': 'True', 'blank': 'True'}),
+            'lead_pl_markup_type': ('django.db.models.fields.CharField', [], {'default': "'textile_pl'", 'max_length': '30', 'blank': 'True'}),
+            'needed_en': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1', 'db_index': 'True'}),
+            'promo': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'published_en': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'published_pl': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'slug_en': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'slug_pl': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'title_en': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'title_pl': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '16', 'db_index': 'True'})
+        }
+    }
+
+    complete_apps = ['migdal']
\ No newline at end of file
diff --git a/migdal/models.py b/migdal/models.py
index d735ba6..90a2d3c 100644
--- a/migdal/models.py
+++ b/migdal/models.py
@@ -30,15 +30,13 @@ add_translatable(Category, {
 
 
 class Entry(models.Model):
-    #type = models.CharField(max_length=16,
-    #        choices=((t.db, t.slug) for t in settings.TYPES),
-    #        db_index=True)
     type = models.CharField(max_length=16,
             choices=((t.db, t.slug) for t in settings.TYPES),
             db_index=True)
     date = models.DateTimeField(auto_now_add=True, db_index=True)
     author = models.CharField(_('author'), max_length=128)
-    author_email = models.EmailField(_('author email'), max_length=128, null=True, blank=True)
+    author_email = models.EmailField(_('author email'), max_length=128, null=True, blank=True,
+            help_text=_('Used only to display gravatar and send notifications.'))
     image = models.ImageField(_('image'), upload_to='entry/image/', null=True, blank=True)
     promo = models.BooleanField(_('promoted'), default=False)
     categories = models.ManyToManyField(Category, null=True, blank=True)
@@ -66,29 +64,23 @@ class Entry(models.Model):
     def get_type(self):
         return dict(settings.TYPES_DICT)[self.type]
 
-
-add_translatable(Entry, languages=settings.OBLIGATORY_LANGUAGES, fields={
-    'slug': models.SlugField(unique=True, db_index=True),
-    'title': models.CharField(_('title'), max_length=255),
-    'lead': MarkupField(_('lead'), markup_type='textile_pl'),
-})
-
 add_translatable(Entry, languages=settings.OPTIONAL_LANGUAGES, fields={
-    'slug': models.SlugField(unique=True, db_index=True, null=True, blank=True),
-    'title': models.CharField(_('title'), max_length=255, null=True, blank=True),
-    'lead': MarkupField(_('lead'), markup_type='textile_pl', null=True, blank=True),
     'needed': models.CharField(_('needed'), max_length=1, db_index=True, choices=(
                 ('n', _('Unneeded')), ('w', _('Needed')), ('y', _('Done'))),
                 default='n'),
 })
 
 add_translatable(Entry, {
-    'body': MarkupField(_('body'), markup_type='textile_pl', null=True, blank=True),
+    'slug': models.SlugField(unique=True, db_index=True, null=True, blank=True),
+    'title': models.CharField(_('title'), max_length=255, null=True, blank=True),
+    'lead': MarkupField(_('lead'), markup_type='textile_pl', null=True, blank=True,
+                help_text=_('Use Textile syntax.')),
+    'body': MarkupField(_('body'), markup_type='textile_pl', null=True, blank=True,
+                help_text=_('Use Textile syntax.')),
     'published': models.BooleanField(_('published'), default=False),
 })
 
 
-
 class Attachment(models.Model):
     file = models.FileField(_('file'), upload_to='entry/attach/')
     entry = models.ForeignKey(Entry)
diff --git a/migdal/settings.py b/migdal/settings.py
index 4331c07..3d5bd01 100644
--- a/migdal/settings.py
+++ b/migdal/settings.py
@@ -22,7 +22,8 @@ TYPES = app_setting('MIGDAL_TYPES', (
         ))
 TYPES_DICT = dict((t.db, t) for t in TYPES)
 TYPES_ON_MAIN = tuple(t.db for t in TYPES if t.on_main)
-# FIXME: if only news is on_main, `news/` should either throw 404 or redirect to main
+TYPE_SUBMIT = 'news'
+
 
 LANGUAGES = app_setting('MIGDAL_LANGUAGES', settings.LANGUAGES)
 LANGUAGE_CODE = app_setting('MIGDAL_LANGUAGE_CODE', settings.LANGUAGE_CODE)
diff --git a/migdal/templates/django_comments_xtd/email_followup_comment.html b/migdal/templates/django_comments_xtd/email_followup_comment.html
new file mode 100644
index 0000000..1987906
--- /dev/null
+++ b/migdal/templates/django_comments_xtd/email_followup_comment.html
@@ -0,0 +1,24 @@
+{% load i18n %}
+{{ user_name }},
+
+PojawiÅ siÄ nowy komentarz w wÄ
tku z Twoim udziaÅem.
+(There is a new comment following up yours.)
+
+
+{% if content_object.published_pl %}{% language 'pl' %}
+  â{{ content_object.title }}â
+{% endlanguage %}{% endif %}
+{% if content_object.published_en %}{% language 'en' %}
+  
+  â{{ content_object.title}}
+{% endlanguage %}{% endif %}
+
+
+{{ comment.name }}, {{ comment.submit_date|date:"SHORT_DATE_FORMAT" }}:
+
+{{ comment.comment }}
+
+
+--
+{{ site }}
+
diff --git a/migdal/templates/django_comments_xtd/email_followup_comment.txt b/migdal/templates/django_comments_xtd/email_followup_comment.txt
index 7d9df1d..a1ca8f1 100755
--- a/migdal/templates/django_comments_xtd/email_followup_comment.txt
+++ b/migdal/templates/django_comments_xtd/email_followup_comment.txt
@@ -1 +1,18 @@
-POWIADOMIENIE
\ No newline at end of file
+{% load i18n %}{{ user_name }},
+
+PojawiÅ siÄ nowy komentarz w wÄ
tku z Twoim udziaÅem.
+(There is a new comment following up yours.)
+
+{% if content_object.published_pl %}{% language 'pl' %}Polska wersja: â{{ content_object.title }}â
+    http://{{ site.domain }}{{ content_object.get_absolute_url }}{% endlanguage %}{% endif %}
+{% if content_object.published_en %}{% language 'en' %}English version: â{{ content_object.title }}â
+    http://{{ site.domain }}{{ content_object.get_absolute_url }}{% endlanguage %}{% endif %}
+
+
+{{ comment.name }}, {{ comment.submit_date|date:"SHORT_DATE_FORMAT" }}:
+--------
+{{ comment.comment }}
+
+
+-- 
+{{ site }}
diff --git a/migdal/templates/migdal/entry/entry_begin.html b/migdal/templates/migdal/entry/entry_begin.html
index fbec320..351148e 100755
--- a/migdal/templates/migdal/entry/entry_begin.html
+++ b/migdal/templates/migdal/entry/entry_begin.html
@@ -1,3 +1,4 @@
+{% load i18n %}
 {% load gravatar %}
 
 
@@ -6,6 +7,20 @@
 
 {{ object.date }}
 {{ object.author }}
+
+{% if request.LANGUAGE_CODE == 'pl' %}
+    {% if object.published_en %}
+        {% language 'en' %}
+            
English version
+        {% endlanguage %}
+    {% endif %}
+{% elif object.published_pl %}
+        {% language 'pl' %}
+            
polska wersja
+        {% endlanguage %}
+{% endif %}
+
+
 {% for category in object.categories.all %}
     
{{ category }}
 {% endfor %}
diff --git a/migdal/templates/migdal/entry/entry_detail.html b/migdal/templates/migdal/entry/entry_detail.html
index 6ef926a..9812a59 100755
--- a/migdal/templates/migdal/entry/entry_detail.html
+++ b/migdal/templates/migdal/entry/entry_detail.html
@@ -12,7 +12,7 @@
 
 {% if entry.get_type.commentable %}
     {% render_comment_list for entry %}
-    {% render_comment_form for entry %}
+    {% entry_comment_form entry %}
 {% endif %}
 
 
 
diff --git a/migdal/templates/migdal/entry/entry_list.html b/migdal/templates/migdal/entry/entry_list.html
index d68673b..9f3ec41 100755
--- a/migdal/templates/migdal/entry/entry_list.html
+++ b/migdal/templates/migdal/entry/entry_list.html
@@ -17,6 +17,10 @@
 {% endif %}
 
 
+{% if submit %}
+    {% trans "Submit a new story." %}
+{% endif %}
+
 {% for object in object_list %}
     {% entry_short object %}
 {% endfor %}
diff --git a/migdal/templates/migdal/entry/info/entry_begin.html b/migdal/templates/migdal/entry/info/entry_begin.html
index 7544b6f..256a38d 100755
--- a/migdal/templates/migdal/entry/info/entry_begin.html
+++ b/migdal/templates/migdal/entry/info/entry_begin.html
@@ -1,4 +1,21 @@
 
+
+
+{% if request.LANGUAGE_CODE == 'pl' %}
+    {% if object.published_en %}
+        {% language 'en' %}
+            
English version
+        {% endlanguage %}
+    {% endif %}
+{% elif object.published_pl %}
+    {{ request.LANGUAGE_CODE }}
+    {% language 'pl' %}
+        
polska wersja
+    {% endlanguage %}
+{% endif %}
+
 
+
+
 {% if object.image %}
     
 {% endif %}
diff --git a/migdal/templates/migdal/entry/submit.html b/migdal/templates/migdal/entry/submit.html
new file mode 100755
index 0000000..14906ba
--- /dev/null
+++ b/migdal/templates/migdal/entry/submit.html
@@ -0,0 +1,19 @@
+{% extends "base.html" %}
+{% load url from future %}
+{% load i18n %}
+
+{% block "body" %}
+
+{% trans "Submit new story" %}
+
+
+    
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/migdal/templates/migdal/entry/submit_thanks.html b/migdal/templates/migdal/entry/submit_thanks.html
new file mode 100755
index 0000000..48a55d1
--- /dev/null
+++ b/migdal/templates/migdal/entry/submit_thanks.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+{% load url from future %}
+{% load i18n %}
+
+{% block "body" %}
+
+{% trans "Thanks for submitting" %}
+
+{% blocktrans %}
+Thank you for submitting this new story, it's waiting for moderation.
+If you provided an email, we'll inform you about changes in it's status
+and comments.
+{% endblocktrans %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/migdal/templates/migdal/mail/manager_new_entry.txt b/migdal/templates/migdal/mail/manager_new_entry.txt
new file mode 100755
index 0000000..59703e2
--- /dev/null
+++ b/migdal/templates/migdal/mail/manager_new_entry.txt
@@ -0,0 +1,14 @@
+{% load url from future %}W serwisie pojawiÅ siÄ nowy wpis.
+http://localhost:8000{% url 'admin:migdal_entry_change' object.pk %}
+
+Autor: {{ object.author|default_if_none:"" }}
+E-mail: {{ object.author_email|default_if_none:"" }}
+TytuÅ [pl]: {{ object.title_pl|default_if_none:"" }}
+TytuÅ [en]: {{ object.title_en|default_if_none:"" }}
+Kategorie: {{ object.categories.all|join:", " }}
+
+---
+{{ object.lead_pl.raw }}
+---
+{{ object.lead_en.raw }}
+---
\ No newline at end of file
diff --git a/migdal/templatetags/migdal_tags.py b/migdal/templatetags/migdal_tags.py
index b9722b6..5578c5d 100644
--- a/migdal/templatetags/migdal_tags.py
+++ b/migdal/templatetags/migdal_tags.py
@@ -3,29 +3,30 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django_comments_xtd.models import XtdComment
+from django.contrib import comments
 from django import template
 from migdal.models import Category
 
 register = template.Library()
 
 
-@register.simple_tag
-def entry_begin(entry):
+@register.simple_tag(takes_context=True)
+def entry_begin(context, entry):
     t = template.loader.select_template((
         'migdal/entry/%s/entry_begin.html' % entry.type,
         'migdal/entry/entry_begin.html',
     ))
-    context = {'object': entry}
+    context.update({'object': entry})
     return t.render(template.Context(context))
 
 
-@register.simple_tag
-def entry_short(entry):
+@register.simple_tag(takes_context=True)
+def entry_short(context, entry):
     t = template.loader.select_template((
         'migdal/entry/%s/entry_short.html' % entry.type,
         'migdal/entry/entry_short.html',
     ))
-    context = {'object': entry}
+    context.update({'object': entry})
     return t.render(template.Context(context))
 
 
@@ -39,3 +40,11 @@ def categories(context):
 def last_comments(limit=10):
     return {'object_list': 
         XtdComment.objects.filter(is_public=True, is_removed=False).order_by('-submit_date')[:limit]}
+
+
+@register.inclusion_tag(['comments/form.html'])
+def entry_comment_form(entry):
+    return {
+            'form': comments.get_form()(entry),
+            'next': entry.get_absolute_url(),
+        }
\ No newline at end of file
diff --git a/migdal/urls.py b/migdal/urls.py
index b600cef..dec95bd 100644
--- a/migdal/urls.py
+++ b/migdal/urls.py
@@ -28,6 +28,9 @@ urlpatterns = i18n_patterns('',
     # main page
     url(r'^$', 'migdal.views.entry_list', name='migdal_main'),
     url(r'^rss.xml$', feeds.EntriesFeed(), name='migdal_main_feed'),
+    # submit new entry
+    url(string_concat(r'^', _('submit'), r'/$'), 'migdal.views.submit', name='migdal_submit'),
+    url(string_concat(r'^', _('submit'), r'/', _('thanks'), r'$'), 'migdal.views.submit_thanks', name='migdal_submit_thanks'),
     # category
     url(string_concat(r'^', _('categories'), r'/(?P[^/]*)/$'),
         'migdal.views.entry_list', name='migdal_category'),
diff --git a/migdal/views.py b/migdal/views.py
index d705d34..42a2a39 100644
--- a/migdal/views.py
+++ b/migdal/views.py
@@ -2,33 +2,39 @@
 # This file is part of PrawoKultury, licensed under GNU Affero GPLv3 or later.
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-from django.shortcuts import get_object_or_404, render
+from django.shortcuts import get_object_or_404, render, redirect
 from migdal import api
+from migdal.forms import get_submit_form
 from migdal.models import Category, Entry
-from migdal.settings import TYPES_DICT
+from migdal.settings import TYPES_DICT, TYPES_ON_MAIN, TYPE_SUBMIT
 
 
 def entry_list(request, type_db=None, category_slug=None):
     lang = request.LANGUAGE_CODE
     templates = ["migdal/entry/entry_list.html"]
 
-    if category_slug:
-        category = get_object_or_404(Category, **{'slug_%s' % lang: category_slug})
-    else:
-        category = None
     if type_db:
+        if TYPES_ON_MAIN == (type_db,):
+            return redirect('migdal_main')
         entry_type = TYPES_DICT[type_db]
-        # TODO: if it's the only on main, redirect to main
         templates = ["migdal/entry/%s/entry_list.html" % type_db] + templates
+        submit = type_db == TYPE_SUBMIT
     else:
+        submit = TYPES_ON_MAIN == (TYPE_SUBMIT,)
         entry_type = None
 
+    if category_slug:
+        category = get_object_or_404(Category, **{'slug_%s' % lang: category_slug})
+    else:
+        category = None
+
     object_list = api.entry_list(entry_type=entry_type, category=category)
 
     return render(request, templates, {
             'object_list': object_list,
             'category': category,
             'entry_type': entry_type,
+            'submit': submit,
         })
 
 
@@ -42,3 +48,20 @@ def entry(request, type_db, slug):
     if type_db is not None:
         templates = ["migdal/entry/%s/entry_detail.html" % type_db] + templates
     return render(request, templates, {'entry': entry})
+
+
+def submit(request):
+    if request.method == 'POST':
+        submit_form = get_submit_form(request.POST)
+        if submit_form.is_valid():
+            submit_form.save()
+            return redirect('migdal_submit_thanks')
+    else:
+        submit_form = get_submit_form()
+
+    return render(request, 'migdal/entry/submit.html', {
+            'submit_form': submit_form,
+        })
+
+def submit_thanks(request):
+    return render(request, "migdal/entry/submit_thanks.html")
\ No newline at end of file
diff --git a/slughifi.py b/slughifi.py
new file mode 100644
index 0000000..fe5c9e3
--- /dev/null
+++ b/slughifi.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+import re
+from types import UnicodeType
+
+from django.template.defaultfilters import slugify
+
+# default unicode character mapping ( you may not see some chars, leave as is )
+char_map = {u'Ã': 'A', u'Ã': 'A', u'Ã': 'A', u'Ã': 'A', u'Ã': 'Ae', u'Ã
': 'A', u'Ã': 'A', u'Ä': 'A', u'Ä': 'A', u'Ä': 'A', u'Ã': 'C', u'Ä': 'C', u'Ä': 'C', u'Ä': 'C', u'Ä': 'C', u'Ä': 'D', u'Ä': 'D', u'Ã': 'E', u'Ã': 'E', u'Ã': 'E', u'Ã': 'E', u'Ä': 'E', u'Ä': 'E', u'Ä': 'E', u'Ä': 'E', u'Ä': 'E', u'Ä': 'G', u'Ä': 'G', u'Ä ': 'G', u'Ä¢': 'G', u'Ĥ': 'H', u'Ħ': 'H', u'Ã': 'I', u'Ã': 'I', u'Ã': 'I', u'Ã': 'I', u'Ī': 'I', u'Ĩ': 'I', u'Ĭ': 'I', u'Ä®': 'I', u'İ': 'I', u'IJ': 'IJ', u'Ä´': 'J', u'Ķ': 'K', u'Ľ': 'K', u'Ĺ': 'K', u'Ä»': 'K', u'Ä¿': 'K', u'Å': 'L', u'Ã': 'N', u'Å': 'N', u'Å': 'N', u'Å
': 'N', u'Å': 'N', u'Ã': 'O', u'Ã': 'O', u'Ã': 'O', u'Ã': 'O', u'Ã': 'Oe', u'Ã': 'O', u'Å': 'O', u'Å': 'O', u'Å': 'O', u'Å': 'OE', u'Å': 'R', u'Å': 'R', u'Å': 'R', u'Å': 'S', u'Å': 'S', u'Å': 'S', u'È': 'S', u'Å ': 'S', u'Ť': 'T', u'Å¢': 'T', u'Ŧ': 'T', u'È': 'T', u'Ã': 'U', u'Ã': 'U', u'Ã': 'U', u'Ã': 'Ue', u'Ū': 'U', u'Å®': 'U', u'Ű': 'U', u'Ŭ': 'U', u'Ũ': 'U', u'Ų': 'U', u'Å´': 'W', u'Ŷ': 'Y', u'Ÿ': 'Y', u'Ã': 'Y', u'Ź': 'Z', u'Å»': 'Z', u'Ž': 'Z', u'à': 'a', u'á': 'a', u'â': 'a', u'ã': 'a', u'ä': 'ae', u'Ä': 'a', u'Ä
': 'a', u'Ä': 'a', u'Ã¥': 'a', u'æ': 'ae', u'ç': 'c', u'Ä': 'c', u'Ä': 'c', u'Ä': 'c', u'Ä': 'c', u'Ä': 'd', u'Ä': 'd', u'è': 'e', u'é': 'e', u'ê': 'e', u'ë': 'e', u'Ä': 'e', u'Ä': 'e', u'Ä': 'e', u'Ä': 'e', u'Ä': 'e', u'Æ': 'f', u'Ä': 'g', u'Ä': 'g', u'Ä¡': 'g', u'Ä£': 'g', u'Ä¥': 'h', u'ħ': 'h', u'ì': 'i', u'Ã': 'i', u'î': 'i', u'ï': 'i', u'Ä«': 'i', u'Ä©': 'i', u'Ä': 'i', u'į': 'i', u'ı': 'i', u'ij': 'ij', u'ĵ': 'j', u'Ä·': 'k', u'ĸ': 'k', u'Å': 'l', u'ľ': 'l', u'ĺ': 'l', u'ļ': 'l', u'Å': 'l', u'ñ': 'n', u'Å': 'n', u'Å': 'n', u'Å': 'n', u'Å': 'n', u'Å': 'n', u'ò': 'o', u'ó': 'o', u'ô': 'o', u'õ': 'o', u'ö': 'oe', u'ø': 'o', u'Å': 'o', u'Å': 'o', u'Å': 'o', u'Å': 'oe', u'Å': 'r', u'Å': 'r', u'Å': 'r', u'Å': 's', u'Å¡': 's', u'Å¥': 't', u'ù': 'u', u'ú': 'u', u'û': 'u', u'ü': 'ue', u'Å«': 'u', u'ů': 'u', u'ű': 'u', u'Å': 'u', u'Å©': 'u', u'ų': 'u', u'ŵ': 'w', u'ÿ': 'y', u'ý': 'y', u'Å·': 'y', u'ż': 'z', u'ź': 'z', u'ž': 'z', u'Ã': 'ss', u'Å¿': 'ss', u'Î': 'A', u'Î': 'A', u'á¼': 'A', u'á¼': 'A', u'á¼': 'A', u'á¼': 'A', u'á¼': 'A', u'á¼': 'A', u'á¼': 'A', u'á¼': 'A', u'á¾': 'A', u'á¾': 'A', u'á¾': 'A', u'á¾': 'A', u'á¾': 'A', u'á¾': 'A', u'á¾': 'A', u'á¾': 'A', u'Ᾰ': 'A', u'á¾¹': 'A', u'Ὰ': 'A', u'á¾»': 'A', u'á¾¼': 'A', u'Î': 'B', u'Î': 'G', u'Î': 'D', u'Î': 'E', u'Î': 'E', u'á¼': 'E', u'á¼': 'E', u'á¼': 'E', u'á¼': 'E', u'á¼': 'E', u'á¼': 'E', u'á¿': 'E', u'á¿': 'E', u'Î': 'Z', u'Î': 'I', u'Î': 'I', u'Ἠ': 'I', u'Ἡ': 'I', u'Ἢ': 'I', u'Ἣ': 'I', u'Ἤ': 'I', u'á¼': 'I', u'á¼®': 'I', u'Ἧ': 'I', u'á¾': 'I', u'á¾': 'I', u'á¾': 'I', u'á¾': 'I', u'á¾': 'I', u'á¾': 'I', u'á¾': 'I', u'á¾': 'I', u'á¿': 'I', u'á¿': 'I', u'á¿': 'I', u'Î': 'TH', u'Î': 'I', u'Î': 'I', u'Ϊ': 'I', u'Ἰ': 'I', u'á¼¹': 'I', u'Ἲ': 'I', u'á¼»': 'I', u'á¼¼': 'I', u'á¼½': 'I', u'á¼¾': 'I', u'Ἷ': 'I', u'á¿': 'I', u'á¿': 'I', u'á¿': 'I', u'á¿': 'I', u'Î': 'K', u'Î': 'L', u'Î': 'M', u'Î': 'N', u'Î': 'KS', u'Î': 'O', u'Î': 'O', u'á½': 'O', u'á½': 'O', u'á½': 'O', u'á½': 'O', u'á½': 'O', u'á½': 'O', u'Ὸ': 'O', u'Ό': 'O', u'Π': 'P', u'Ρ': 'R', u'Ῥ': 'R', u'Σ': 'S', u'Τ': 'T', u'Î¥': 'Y', u'Î': 'Y', u'Ϋ': 'Y', u'á½': 'Y', u'á½': 'Y', u'á½': 'Y', u'á½': 'Y', u'Ῠ': 'Y', u'á¿©': 'Y', u'Ὺ': 'Y', u'á¿«': 'Y', u'Φ': 'F', u'Χ': 'X', u'Ψ': 'PS', u'Ω': 'O', u'Î': 'O', u'Ὠ': 'O', u'Ὡ': 'O', u'Ὢ': 'O', u'Ὣ': 'O', u'Ὤ': 'O', u'á½': 'O', u'á½®': 'O', u'Ὧ': 'O', u'ᾨ': 'O', u'ᾩ': 'O', u'ᾪ': 'O', u'ᾫ': 'O', u'ᾬ': 'O', u'á¾': 'O', u'á¾®': 'O', u'ᾯ': 'O', u'Ὼ': 'O', u'á¿»': 'O', u'ῼ': 'O', u'α': 'a', u'ά': 'a', u'á¼': 'a', u'á¼': 'a', u'á¼': 'a', u'á¼': 'a', u'á¼': 'a', u'á¼
': 'a', u'á¼': 'a', u'á¼': 'a', u'á¾': 'a', u'á¾': 'a', u'á¾': 'a', u'á¾': 'a', u'á¾': 'a', u'á¾
': 'a', u'á¾': 'a', u'á¾': 'a', u'á½°': 'a', u'á½±': 'a', u'á¾°': 'a', u'á¾±': 'a', u'á¾²': 'a', u'á¾³': 'a', u'á¾´': 'a', u'á¾¶': 'a', u'á¾·': 'a', u'β': 'b', u'γ': 'g', u'δ': 'd', u'ε': 'e', u'Î': 'e', u'á¼': 'e', u'á¼': 'e', u'á¼': 'e', u'á¼': 'e', u'á¼': 'e', u'á¼': 'e', u'á½²': 'e', u'á½³': 'e', u'ζ': 'z', u'η': 'i', u'ή': 'i', u'á¼ ': 'i', u'ἡ': 'i', u'á¼¢': 'i', u'á¼£': 'i', u'ἤ': 'i', u'á¼¥': 'i', u'ἦ': 'i', u'á¼§': 'i', u'á¾': 'i', u'á¾': 'i', u'á¾': 'i', u'á¾': 'i', u'á¾': 'i', u'á¾': 'i', u'á¾': 'i', u'á¾': 'i', u'á½´': 'i', u'á½µ': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'θ': 'th', u'ι': 'i', u'ί': 'i', u'Ï': 'i', u'Î': 'i', u'á¼°': 'i', u'á¼±': 'i', u'á¼²': 'i', u'á¼³': 'i', u'á¼´': 'i', u'á¼µ': 'i', u'á¼¶': 'i', u'á¼·': 'i', u'á½¶': 'i', u'á½·': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'á¿': 'i', u'κ': 'k', u'λ': 'l', u'μ': 'm', u'ν': 'n', u'ξ': 'ks', u'ο': 'o', u'Ï': 'o', u'á½': 'o', u'á½': 'o', u'á½': 'o', u'á½': 'o', u'á½': 'o', u'á½
': 'o', u'ὸ': 'o', u'á½¹': 'o', u'Ï': 'p', u'Ï': 'r', u'ῤ': 'r', u'á¿¥': 'r', u'Ï': 's', u'Ï': 's', u'Ï': 't', u'Ï
': 'y', u'Ï': 'y', u'Ï': 'y', u'ΰ': 'y', u'á½': 'y', u'á½': 'y', u'á½': 'y', u'á½': 'y', u'á½': 'y', u'á½': 'y', u'á½': 'y', u'á½': 'y', u'ὺ': 'y', u'á½»': 'y', u'á¿ ': 'y', u'á¿¡': 'y', u'á¿¢': 'y', u'á¿£': 'y', u'ῦ': 'y', u'á¿§': 'y', u'Ï': 'f', u'Ï': 'x', u'Ï': 'ps', u'Ï': 'o', u'Ï': 'o', u'á½ ': 'o', u'ὡ': 'o', u'á½¢': 'o', u'á½£': 'o', u'ὤ': 'o', u'á½¥': 'o', u'ὦ': 'o', u'á½§': 'o', u'á¾ ': 'o', u'ᾡ': 'o', u'á¾¢': 'o', u'á¾£': 'o', u'ᾤ': 'o', u'á¾¥': 'o', u'ᾦ': 'o', u'á¾§': 'o', u'á½¼': 'o', u'á½½': 'o', u'ῲ': 'o', u'ῳ': 'o', u'á¿´': 'o', u'á¿¶': 'o', u'á¿·': 'o', u'¨': '', u'Î
': '', u'᾿': '', u'῾': '', u'á¿': '', u'á¿': '', u'á¿': '', u'á¿': '', u'á¿': '', u'á¿': '', u'á¿': '', u'á¿': '', u'Î': '', u'á¿®': '', u'`': '', u'á¿': '', u'ͺ': '', u'á¾½': '', u'Ð': 'A', u'Ð': 'B', u'Ð': 'V', u'Ð': 'G', u'Ð': 'D', u'Ð': 'E', u'Ð': 'E', u'Ð': 'ZH', u'Ð': 'Z', u'Ð': 'I', u'Ð': 'I', u'Ð': 'K', u'Ð': 'L', u'Ð': 'M', u'Ð': 'N', u'Ð': 'O', u'Ð': 'P', u'Р': 'R', u'С': 'S', u'Т': 'T', u'У': 'U', u'Ф': 'F', u'Ð¥': 'KH', u'Ц': 'TS', u'Ч': 'CH', u'Ш': 'SH', u'Щ': 'SHCH', u'Ы': 'Y', u'Ð': 'E', u'Ю': 'YU', u'Я': 'YA', u'а': 'A', u'б': 'B', u'в': 'V', u'г': 'G', u'д': 'D', u'е': 'E', u'Ñ': 'E', u'ж': 'ZH', u'з': 'Z', u'и': 'I', u'й': 'I', u'к': 'K', u'л': 'L', u'м': 'M', u'н': 'N', u'о': 'O', u'п': 'P', u'Ñ': 'R', u'Ñ': 'S', u'Ñ': 'T', u'Ñ': 'U', u'Ñ': 'F', u'Ñ
': 'KH', u'Ñ': 'TS', u'Ñ': 'CH', u'Ñ': 'SH', u'Ñ': 'SHCH', u'Ñ': 'Y', u'Ñ': 'E', u'Ñ': 'YU', u'Ñ': 'YA', u'Ъ': '', u'Ñ': '', u'Ь': '', u'Ñ': '', u'ð': 'd', u'Ã': 'D', u'þ': 'th', u'Ã': 'TH',
+            u'á': 'a', u'á': 'b', u'á': 'g', u'á': 'd', u'á': 'e', u'á': 'v', u'á': 'z', u'á': 't', u'á': 'i', u'á': 'k', u'á': 'l', u'á': 'm', u'á': 'n', u'á': 'o', u'á': 'p', u'á': 'zh', u'á ': 'r', u'á¡': 's', u'á¢': 't', u'á£': 'u', u'á¤': 'p', u'á¥': 'k', u'á¦': 'gh', u'á§': 'q', u'á¨': 'sh', u'á©': 'ch', u'áª': 'ts', u'á«': 'dz', u'á¬': 'ts', u'á': 'ch', u'á®': 'kh', u'á¯': 'j', u'á°': 'h' }
+
+def replace_char(m):
+    char = m.group()
+    if char_map.has_key(char):
+        return char_map[char]
+    else:
+        return char
+
+def slughifi(value, do_slugify=True, overwrite_char_map={}):
+    """
+        High Fidelity slugify - slughifi.py, v 0.1
+
+        Examples :
+
+        >>> text = 'C\'est déjà l\'été.'
+
+        >>> slughifi(text)
+        'cest-deja-lete'
+
+        >>> slughifi(text, overwrite_char_map={u'\'': '-',})
+        'c-est-deja-l-ete'
+
+        >>> slughifi(text, do_slugify=False)
+        "C'est deja l'ete."
+
+        # Normal slugify removes accented characters
+        >>> slugify(text)
+        'cest-dj-lt'
+
+    """
+
+    # unicodification
+    if type(value) != UnicodeType:
+        value = unicode(value, 'utf-8', 'ignore')
+
+    # overwrite chararcter mapping
+    char_map.update(overwrite_char_map)
+
+    # try to replace chars
+    value = re.sub('[^a-zA-Z0-9\\s\\-]{1}', replace_char, value)
+
+    # apply django default slugify
+    if do_slugify:
+        value = slugify(value)
+
+    return value.encode('ascii', 'ignore')
+