summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-04-09 22:57:21 -0500
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-04-09 22:57:21 -0500
commit2841a5b8bd78f01c81143f889220fafd90784949 (patch)
treefddef8671966accf8224e73c5003a674177203ca
parentf95609f40c1560bfa04b667125d5659dbfd772e3 (diff)
downloadaskbot-2841a5b8bd78f01c81143f889220fafd90784949.tar.gz
askbot-2841a5b8bd78f01c81143f889220fafd90784949.tar.bz2
askbot-2841a5b8bd78f01c81143f889220fafd90784949.zip
added response by email when post was added to the moderation queue, also comments can be now moderated
-rw-r--r--askbot/migrations/0118_auto__add_field_postrevision_by_email.py304
-rw-r--r--askbot/models/__init__.py62
-rw-r--r--askbot/models/post.py219
-rw-r--r--askbot/models/question.py14
-rw-r--r--askbot/skins/common/media/js/user.js25
-rw-r--r--askbot/skins/default/templates/macros.html2
6 files changed, 529 insertions, 97 deletions
diff --git a/askbot/migrations/0118_auto__add_field_postrevision_by_email.py b/askbot/migrations/0118_auto__add_field_postrevision_by_email.py
new file mode 100644
index 00000000..7c304d1e
--- /dev/null
+++ b/askbot/migrations/0118_auto__add_field_postrevision_by_email.py
@@ -0,0 +1,304 @@
+# -*- 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 'PostRevision.by_email'
+ db.add_column('askbot_postrevision', 'by_email',
+ self.gf('django.db.models.fields.BooleanField')(default=False),
+ keep_default=False)
+
+ def backwards(self, orm):
+ # Deleting field 'PostRevision.by_email'
+ db.delete_column('askbot_postrevision', 'by_email')
+
+ models = {
+ 'askbot.activity': {
+ 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},
+ 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True'}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
+ 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'symmetrical': 'False', 'through': "orm['askbot.ActivityAuditStatus']", 'to': "orm['auth.User']"}),
+ 'summary': ('django.db.models.fields.TextField', [], {'default': "''"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.activityauditstatus': {
+ 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'},
+ 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.anonymousanswer': {
+ 'Meta': {'object_name': 'AnonymousAnswer'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['askbot.Post']"}),
+ 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'askbot.anonymousquestion': {
+ 'Meta': {'object_name': 'AnonymousQuestion'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+ },
+ 'askbot.award': {
+ 'Meta': {'object_name': 'Award', 'db_table': "u'award'"},
+ 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['askbot.BadgeData']"}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.badgedata': {
+ 'Meta': {'ordering': "('slug',)", 'object_name': 'BadgeData'},
+ 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['askbot.Award']", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'})
+ },
+ 'askbot.emailfeedsetting': {
+ 'Meta': {'unique_together': "(('subscriber', 'feed_type'),)", 'object_name': 'EmailFeedSetting'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'frequency': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '8'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'reported_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'subscriber': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notification_subscriptions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.favoritequestion': {
+ 'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Thread']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.groupmembership': {
+ 'Meta': {'object_name': 'GroupMembership'},
+ 'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_memberships'", 'to': "orm['askbot.Tag']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'group_memberships'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.groupprofile': {
+ 'Meta': {'object_name': 'GroupProfile'},
+ 'group_tag': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'group_profile'", 'unique': 'True', 'to': "orm['askbot.Tag']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'})
+ },
+ 'askbot.markedtag': {
+ 'Meta': {'object_name': 'MarkedTag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['askbot.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.post': {
+ 'Meta': {'object_name': 'Post'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['auth.User']"}),
+ 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_posts'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_posts'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_posts'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'old_answer_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+ 'old_comment_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+ 'old_question_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'post_type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'posts'", 'null': 'True', 'blank': 'True', 'to': "orm['askbot.Thread']"}),
+ 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'askbot.postrevision': {
+ 'Meta': {'ordering': "('-revision',)", 'unique_together': "(('post', 'revision'),)", 'object_name': 'PostRevision'},
+ 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+ 'approved_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'approved_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'postrevisions'", 'to': "orm['auth.User']"}),
+ 'by_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'revised_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'revision_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '125', 'blank': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '300', 'blank': 'True'})
+ },
+ 'askbot.questionview': {
+ 'Meta': {'object_name': 'QuestionView'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'viewed'", 'to': "orm['askbot.Post']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.replyaddress': {
+ 'Meta': {'object_name': 'ReplyAddress'},
+ 'address': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}),
+ 'allowed_from_email': ('django.db.models.fields.EmailField', [], {'max_length': '150'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reply_addresses'", 'to': "orm['askbot.Post']"}),
+ 'response_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edit_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'used_at': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True', 'blank': 'True'}),
+ 'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.tag': {
+ 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag', 'db_table': "u'tag'"},
+ 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['auth.User']"}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'tag_wiki': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'described_tag'", 'unique': 'True', 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+ },
+ 'askbot.thread': {
+ 'Meta': {'object_name': 'Thread'},
+ 'accepted_answer': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['askbot.Post']"}),
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'answer_accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
+ 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+ 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'unused_favorite_threads'", 'symmetrical': 'False', 'through': "orm['askbot.FavoriteQuestion']", 'to': "orm['auth.User']"}),
+ 'favourite_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_threads'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'unused_last_active_in_threads'", 'to': "orm['auth.User']"}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'threads'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+ },
+ 'askbot.vote': {
+ 'Meta': {'unique_together': "(('user', 'voted_post'),)", 'object_name': 'Vote', 'db_table': "u'vote'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['auth.User']"}),
+ 'vote': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'voted_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['askbot.Post']"})
+ },
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ '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': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),
+ 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'consecutive_days_visit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}),
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'display_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
+ 'email_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ignored_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'interesting_tags': ('django.db.models.fields.TextField', [], {'blank': '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'}),
+ 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),
+ 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'show_country': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
+ 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ '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'}),
+ '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'})
+ }
+ }
+
+ complete_apps = ['askbot'] \ No newline at end of file
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 7067ef94..3774bc7d 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -988,6 +988,7 @@ def user_post_comment(
parent_post = None,
body_text = None,
timestamp = None,
+ by_email = False
):
"""post a comment on behalf of the user
to parent_post
@@ -1006,9 +1007,11 @@ def user_post_comment(
user = self,
comment = body_text,
added_at = timestamp,
+ by_email = by_email
)
parent_post.thread.invalidate_cached_data()
- award_badges_signal.send(None,
+ award_badges_signal.send(
+ None,
event = 'post_comment',
actor = self,
context_object = comment,
@@ -1333,7 +1336,8 @@ def user_post_question(
tags = None,
wiki = False,
is_anonymous = False,
- timestamp = None
+ timestamp = None,
+ by_email = False
):
"""makes an assertion whether user can post the question
then posts it and returns the question object"""
@@ -1350,6 +1354,8 @@ def user_post_question(
if timestamp is None:
timestamp = datetime.datetime.now()
+ #todo: split this into "create thread" + "add queston", if text exists
+ #or maybe just add a blank question post anyway
thread = Thread.objects.create_new(
author = self,
title = title,
@@ -1358,6 +1364,7 @@ def user_post_question(
added_at = timestamp,
wiki = wiki,
is_anonymous = is_anonymous,
+ by_email = by_email
)
question = thread._question_post()
if question.author != self:
@@ -1366,42 +1373,60 @@ def user_post_question(
# because they set some attributes for that instance and expect them to be changed also for question.author
return question
-def user_edit_comment(self, comment_post=None, body_text = None):
+@auto_now_timestamp
+def user_edit_comment(
+ self,
+ comment_post=None,
+ body_text = None,
+ timestamp = None,
+ by_email = False
+ ):
"""apply edit to a comment, the method does not
change the comments timestamp and no signals are sent
todo: see how this can be merged with edit_post
todo: add timestamp
"""
self.assert_can_edit_comment(comment_post)
- comment_post.text = body_text
- comment_post.parse_and_save(author = self)
- comment_post.thread.invalidate_cached_data()
+ comment_post.apply_edit(
+ text = body_text,
+ edited_at = timestamp,
+ edited_by = self,
+ by_email = by_email
+ )
def user_edit_post(self,
post = None,
body_text = None,
revision_comment = None,
- timestamp = None):
+ timestamp = None,
+ by_email = False
+ ):
"""a simple method that edits post body
todo: unify it in the style of just a generic post
this requires refactoring of underlying functions
because we cannot bypass the permissions checks set within
"""
if post.post_type == 'comment':
- self.edit_comment(comment_post = post, body_text = body_text)
+ self.edit_comment(
+ comment_post = post,
+ body_text = body_text,
+ by_email = by_email
+ )
elif post.post_type == 'answer':
self.edit_answer(
answer = post,
body_text = body_text,
timestamp = timestamp,
- revision_comment = revision_comment
+ revision_comment = revision_comment,
+ by_email = by_email
)
elif post.post_type == 'question':
self.edit_question(
question = post,
body_text = body_text,
timestamp = timestamp,
- revision_comment = revision_comment
+ revision_comment = revision_comment,
+ by_email = by_email
)
elif post.post_type == 'tag_wiki':
post.apply_edit(
@@ -1411,6 +1436,7 @@ def user_edit_post(self,
#todo: summary name clash in question and question revision
comment = revision_comment,
wiki = True,
+ by_email = False
)
else:
raise NotImplementedError()
@@ -1427,9 +1453,11 @@ def user_edit_question(
edit_anonymously = False,
timestamp = None,
force = False,#if True - bypass the assert
+ by_email = False
):
if force == False:
self.assert_can_edit_question(question)
+
question.apply_edit(
edited_at = timestamp,
edited_by = self,
@@ -1440,8 +1468,11 @@ def user_edit_question(
tags = tags,
wiki = wiki,
edit_anonymously = edit_anonymously,
+ by_email = by_email
)
+
question.thread.invalidate_cached_data()
+
award_badges_signal.send(None,
event = 'edit_question',
actor = self,
@@ -1457,7 +1488,8 @@ def user_edit_answer(
revision_comment = None,
wiki = False,
timestamp = None,
- force = False#if True - bypass the assert
+ force = False,#if True - bypass the assert
+ by_email = False
):
if force == False:
self.assert_can_edit_answer(answer)
@@ -1467,6 +1499,7 @@ def user_edit_answer(
text = body_text,
comment = revision_comment,
wiki = wiki,
+ by_email = by_email
)
answer.thread.invalidate_cached_data()
award_badges_signal.send(None,
@@ -1482,7 +1515,8 @@ def user_post_answer(
body_text = None,
follow = False,
wiki = False,
- timestamp = None
+ timestamp = None,
+ by_email = False
):
#todo: move this to assertion - user_assert_can_post_answer
@@ -1494,6 +1528,7 @@ def user_post_answer(
now = datetime.datetime.now()
asked = question.added_at
+ #todo: this is an assertion, must be moved out
if (now - asked < delta and self.reputation < askbot_settings.MIN_REP_TO_ANSWER_OWN_QUESTION):
diff = asked + delta - now
days = diff.days
@@ -1544,7 +1579,8 @@ def user_post_answer(
text = body_text,
added_at = timestamp,
email_notify = follow,
- wiki = wiki
+ wiki = wiki,
+ by_email = by_email
)
answer_post.thread.invalidate_cached_data()
award_badges_signal.send(None,
diff --git a/askbot/models/post.py b/askbot/models/post.py
index 44ce5728..e6e7ec9d 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -158,20 +158,33 @@ class PostManager(BaseQuerySetManager):
post_type = 'tag_wiki'
)
- def create_new(self, thread, author, added_at, text, wiki=False, email_notify=False, post_type=None):
+ def create_new(
+ self,
+ thread,
+ author,
+ added_at,
+ text,
+ parent = None,
+ wiki = False,
+ email_notify = False,
+ post_type = None,
+ by_email = False
+ ):
# TODO: Some of this code will go to Post.objects.create_new
assert(post_type in const.POST_TYPES)
post = Post(
- post_type=post_type,
- thread=thread,
- author=author,
- added_at=added_at,
- wiki=wiki,
- text=text,
+ post_type = post_type,
+ thread = thread,
+ parent = parent,
+ author = author,
+ added_at = added_at,
+ wiki = wiki,
+ text = text,
#.html field is denormalized by the save() call
)
+
if post.wiki:
post.last_edited_by = post.author
post.last_edited_at = added_at
@@ -180,22 +193,34 @@ class PostManager(BaseQuerySetManager):
post.parse_and_save(author=author)
post.add_revision(
- author=author,
- revised_at=added_at,
- text=text,
+ author = author,
+ revised_at = added_at,
+ text = text,
comment = const.POST_STATUS['default_version'],
+ by_email = by_email
)
return post
- def create_new_answer(self, thread, author, added_at, text, wiki=False, email_notify=False):
+ #todo: instead of this, have Thread.add_answer()
+ def create_new_answer(
+ self,
+ thread,
+ author,
+ added_at,
+ text,
+ wiki = False,
+ email_notify = False,
+ by_email = False
+ ):
answer = self.create_new(
thread,
author,
added_at,
text,
wiki = wiki,
- post_type = 'answer'
+ post_type = 'answer',
+ by_email = by_email
)
#set notification/delete
if email_notify:
@@ -204,7 +229,8 @@ class PostManager(BaseQuerySetManager):
thread.followed_by.remove(author)
#update thread data
- thread.answer_count +=1
+ #todo: this totally belongs to some `Thread` class method
+ thread.answer_count += 1
thread.save()
thread.set_last_activity(last_activity_at=added_at, last_activity_by=author) # this should be here because it regenerates cached thread summary html
return answer
@@ -676,22 +702,27 @@ class Post(models.Model):
self._cached_comments = list()
return self._cached_comments
- def add_comment(self, comment=None, user=None, added_at=None):
+ def add_comment(
+ self,
+ comment=None,
+ user=None,
+ added_at=None,
+ by_email = False):
+
if added_at is None:
added_at = datetime.datetime.now()
- if None in (comment ,user):
+ if None in (comment, user):
raise Exception('arguments comment and user are required')
- from askbot.models import Post
- comment = Post(
- post_type='comment',
- thread=self.thread,
- parent=self,
- text=comment,
- author=user,
- added_at=added_at
- )
- comment.parse_and_save(author = user)
+ comment_post = self.__class__.objects.create_new(
+ self.thread,
+ user,
+ added_at,
+ comment,
+ parent = self,
+ post_type = 'comment',
+ by_email = by_email
+ )
self.comment_count = self.comment_count + 1
self.save()
@@ -711,7 +742,7 @@ class Post(models.Model):
# origin_post.last_activity_by = user
# origin_post.save()
- return comment
+ return comment_post
def get_global_tag_based_subscribers(
self,
@@ -1298,7 +1329,16 @@ class Post(models.Model):
def get_tag_names(self):
return self.thread.get_tag_names()
- def __apply_edit(self, edited_at=None, edited_by=None, text=None, comment=None, wiki=False):
+ def __apply_edit(
+ self,
+ edited_at = None,
+ edited_by = None,
+ text = None,
+ comment = None,
+ wiki = False,
+ edit_anonymously = False,
+ by_email = False
+ ):
if text is None:
text = self.get_latest_revision().text
if edited_at is None:
@@ -1310,26 +1350,40 @@ class Post(models.Model):
self.last_edited_by = edited_by
#self.html is denormalized in save()
self.text = text
- #todo: bug wiki has no effect here
+ self.is_anonymous = edit_anonymously
+
+ #wiki is an eternal trap whence there is no exit
+ if self.wiki == False and wiki == True:
+ self.wiki = True
#must add revision before saving the answer
self.add_revision(
author = edited_by,
revised_at = edited_at,
text = text,
- comment = comment
+ comment = comment,
+ by_email = by_email
)
self.parse_and_save(author = edited_by)
- def _answer__apply_edit(self, edited_at=None, edited_by=None, text=None, comment=None, wiki=False):
+ def _answer__apply_edit(
+ self,
+ edited_at = None,
+ edited_by = None,
+ text = None,
+ comment = None,
+ wiki = False,
+ by_email = False
+ ):
self.__apply_edit(
edited_at = edited_at,
edited_by = edited_by,
text = text,
comment = comment,
- wiki = wiki
+ wiki = wiki,
+ by_email = by_email
)
if edited_at is None:
edited_at = datetime.datetime.now()
@@ -1337,33 +1391,22 @@ class Post(models.Model):
def _question__apply_edit(self, edited_at=None, edited_by=None, title=None,\
text=None, comment=None, tags=None, wiki=False,\
- edit_anonymously = False):
+ edit_anonymously = False,
+ by_email = False
+ ):
+ #todo: the thread editing should happen outside of this
+ #method, then we'll be able to unify all the *__apply_edit
+ #methods
latest_revision = self.get_latest_revision()
#a hack to allow partial edits - important for SE loader
if title is None:
title = self.thread.title
- if text is None:
- text = latest_revision.text
if tags is None:
tags = latest_revision.tagnames
-
- if edited_by is None:
- raise Exception('parameter edited_by is required')
-
if edited_at is None:
edited_at = datetime.datetime.now()
- # Update the Question itself
- self.last_edited_at = edited_at
- self.last_edited_by = edited_by
- self.text = text
- self.is_anonymous = edit_anonymously
-
- #wiki is an eternal trap whence there is no exit
- if self.wiki == False and wiki == True:
- self.wiki = True
-
# Update the Question tag associations
if latest_revision.tagnames != tags:
self.thread.update_tags(tagnames = tags, user = edited_by, timestamp = edited_at)
@@ -1372,29 +1415,39 @@ class Post(models.Model):
self.thread.tagnames = tags
self.thread.save()
- # Create a new revision
- self.add_revision( # has to be called AFTER updating the thread, otherwise it doesn't see new tags and the new title
- author = edited_by,
+ self.__apply_edit(
+ edited_at = edited_at,
+ edited_by = edited_by,
text = text,
- revised_at = edited_at,
- is_anonymous = edit_anonymously,
comment = comment,
+ wiki = wiki,
+ edit_anonymously = edit_anonymously,
+ by_email = by_email
)
- self.parse_and_save(author = edited_by)
-
self.thread.set_last_activity(last_activity_at=edited_at, last_activity_by=edited_by)
def apply_edit(self, *args, **kwargs):
+ #todo: unify this, here we have unnecessary indirection
+ #the question__apply_edit function is backwards:
+ #the title edit and tag edit should apply to thread
+ #not the question post
if self.is_answer():
return self._answer__apply_edit(*args, **kwargs)
elif self.is_question():
return self._question__apply_edit(*args, **kwargs)
- elif self.is_tag_wiki():
+ elif self.is_tag_wiki() or self.is_comment():
return self.__apply_edit(*args, **kwargs)
raise NotImplementedError
- def __add_revision(self, author=None, revised_at=None, text=None, comment=None):
+ def __add_revision(
+ self,
+ author = None,
+ revised_at = None,
+ text = None,
+ comment = None,
+ by_email = False
+ ):
#todo: this may be identical to Question.add_revision
if None in (author, revised_at, text):
raise Exception('arguments author, revised_at and text are required')
@@ -1406,12 +1459,13 @@ class Post(models.Model):
comment = 'No.%s Revision' % rev_no
from askbot.models.post import PostRevision
return PostRevision.objects.create_answer_revision(
- post=self,
- author=author,
- revised_at=revised_at,
- text=text,
- summary=comment,
- revision=rev_no
+ post = self,
+ author = author,
+ revised_at = revised_at,
+ text = text,
+ summary = comment,
+ revision = rev_no,
+ by_email = by_email
)
def _question__add_revision(
@@ -1420,7 +1474,8 @@ class Post(models.Model):
is_anonymous = False,
text = None,
comment = None,
- revised_at = None
+ revised_at = None,
+ by_email = False
):
if None in (author, text):
raise Exception('author, text and comment are required arguments')
@@ -1441,11 +1496,13 @@ class Post(models.Model):
revised_at = revised_at,
tagnames = self.thread.tagnames,
summary = comment,
- text = text
+ text = text,
+ by_email = by_email
)
def add_revision(self, *kargs, **kwargs):
- if self.post_type in ('answer', 'tag_wiki'):
+ #todo: unify these
+ if self.post_type in ('answer', 'comment', 'tag_wiki'):
return self.__add_revision(*kargs, **kwargs)
elif self.is_question():
return self._question__add_revision(*kargs, **kwargs)
@@ -1628,6 +1685,8 @@ class PostRevision(models.Model):
post = models.ForeignKey('askbot.Post', related_name='revisions', null=True, blank=True)
+ #todo: remove this field, as revision type is determined by the
+ #Post.post_type revision_type is a useless field
revision_type = models.SmallIntegerField(choices=REVISION_TYPE_CHOICES) # TODO: remove as we have Post now
revision = models.PositiveIntegerField()
@@ -1640,6 +1699,8 @@ class PostRevision(models.Model):
approved_by = models.ForeignKey(User, null = True, blank = True)
approved_at = models.DateTimeField(null= True, blank = True)
+ by_email = models.BooleanField(default=False)#true, if edited by email
+
# Question-specific fields
title = models.CharField(max_length=300, blank=True, default='')
tagnames = models.CharField(max_length=125, blank=True, default='')
@@ -1691,11 +1752,27 @@ class PostRevision(models.Model):
self.post.thread.approved = False
self.post.thread.save()
#above changes will hide post from the public display
- message = _(
- 'Your post was placed on the moderation queue '
- 'and will be published after the moderator approval.'
- )
- self.author.message_set.create(message = message)
+ if self.by_email:
+ from askbot.utils.mail import send_mail
+ email_context = {
+ 'site': askbot_settings.APP_SHORT_NAME
+ }
+ body_text = _(
+ 'Thank you for your post to %(site)s. '
+ 'It will be published after the moderators review.'
+ ) % email_context
+ send_mail(
+ subject_line = _('your post to %(site)s') % email_context,
+ body_text = body_text,
+ recipient_list = [self.author.email,],
+ )
+
+ else:
+ message = _(
+ 'Your post was placed on the moderation queue '
+ 'and will be published after the moderator approval.'
+ )
+ self.author.message_set.create(message = message)
else:
#In this case, for now we just flag the edit
#for the moderators.
diff --git a/askbot/models/question.py b/askbot/models/question.py
index 51879035..21cf21d0 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -62,7 +62,17 @@ class ThreadManager(models.Manager):
def create(self, *args, **kwargs):
raise NotImplementedError
- def create_new(self, title, author, added_at, wiki, text, tagnames=None, is_anonymous=False):
+ def create_new(
+ self,
+ title,
+ author,
+ added_at,
+ wiki,
+ text,
+ tagnames = None,
+ is_anonymous = False,
+ by_email = False
+ ):
# TODO: Some of this code will go to Post.objects.create_new
thread = super(
@@ -75,6 +85,7 @@ class ThreadManager(models.Manager):
last_activity_by=author
)
+ #todo: code below looks like ``Post.objects.create_new()``
question = Post(
post_type='question',
thread=thread,
@@ -103,6 +114,7 @@ class ThreadManager(models.Manager):
text = text,
comment = const.POST_STATUS['default_version'],
revised_at = added_at,
+ by_email = by_email
)
# INFO: Question has to be saved before update_tags() is called
diff --git a/askbot/skins/common/media/js/user.js b/askbot/skins/common/media/js/user.js
index c0e870b2..24ca060f 100644
--- a/askbot/skins/common/media/js/user.js
+++ b/askbot/skins/common/media/js/user.js
@@ -69,8 +69,11 @@ $(document).ready(function(){
}
}
if (action_type == 'remove_flag'){
- msg = ngettext('Remove all flags on this entry?',
- 'Remove all flags on these entries?', data['id_list'].length);
+ msg = ngettext(
+ 'Remove all flags and approve this entry?',
+ 'Remove all flags and approve these entries?',
+ data['id_list'].length
+ );
if (confirm(msg) === false){
return;
}
@@ -117,15 +120,15 @@ $(document).ready(function(){
}
);
- setupButtonEventHandlers($('.re_expand'),
- function(e){
- e.preventDefault();
- var re_snippet = $(this).find(".re_snippet:first")
- var re_content = $(this).find(".re_content:first")
- $(re_snippet).slideToggle();
- $(re_content).slideToggle();
- }
- );
+ //setupButtonEventHandlers($('.re_expand'),
+ // function(e){
+ // e.preventDefault();
+ // var re_snippet = $(this).find(".re_snippet:first")
+ // var re_content = $(this).find(".re_content:first")
+ // $(re_snippet).slideToggle();
+ // $(re_content).slideToggle();
+ // }
+ //);
$('.badge-context-toggle').each(function(idx, elem){
var context_list = $(elem).parent().next('ul');
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index af04da72..d4871f44 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -39,7 +39,7 @@
</a>
{% if inbox_section == 'flags' %}
<a class="re_expand" href="{{ response.response_url }}">
- <div class="re_snippet">{{ response.response_snippet }}</div>
+ <!--div class="re_snippet">{{ response.response_snippet }}</div-->
<div class="re_content">{{ response.response_content }}</div>
</a>
{% endif %}