summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorByron Corrales <byroncorrales@gmail.com>2012-02-21 16:37:00 -0600
committerByron Corrales <byroncorrales@gmail.com>2012-02-21 16:37:00 -0600
commit5f561d4e690015867eee8ce37b76ab8ae4e456ce (patch)
treefddd2667778f1919968a95acdd8476c04517a9e8
parent5bfa8dd17f8849134e24b72e6b4621d093fec074 (diff)
parentee57d8981757732a83bce1fe96a20c505fa65390 (diff)
downloadaskbot-5f561d4e690015867eee8ce37b76ab8ae4e456ce.tar.gz
askbot-5f561d4e690015867eee8ce37b76ab8ae4e456ce.tar.bz2
askbot-5f561d4e690015867eee8ce37b76ab8ae4e456ce.zip
Merge branch 'askbot/master'
-rw-r--r--askbot/deployment/path_utils.py2
-rw-r--r--askbot/doc/source/changelog.rst8
-rw-r--r--askbot/doc/source/management-commands.rst6
-rw-r--r--askbot/forms.py16
-rw-r--r--askbot/management/commands/build_thread_summary_cache.py10
-rw-r--r--askbot/management/commands/delete_contextless_badge_award_activities.py20
-rw-r--r--askbot/migrations/0050_move_qa_revisions_to_postrevision.py4
-rw-r--r--askbot/migrations/0053_create_threads_for_questions.py5
-rw-r--r--askbot/migrations/0057_transplant_answer_count_data.py5
-rw-r--r--askbot/migrations/0060_view_count_transplant.py5
-rw-r--r--askbot/migrations/0063_transplant_question_closed_datas.py5
-rw-r--r--askbot/migrations/0066_transplant_accepted_answer_data.py8
-rw-r--r--askbot/migrations/0069_transplant_last_activity_data.py5
-rw-r--r--askbot/migrations/0072_transplant_tagnames_data.py5
-rw-r--r--askbot/migrations/0075_transplant_followed_by_data.py7
-rw-r--r--askbot/migrations/0079_transplant_favquestions_data.py5
-rw-r--r--askbot/migrations/0082_transplant_title_data.py5
-rw-r--r--askbot/migrations/0086_transplant_question_tags_data.py7
-rw-r--r--askbot/migrations/0090_postize_q_a_c.py13
-rw-r--r--askbot/migrations/0092_postize_vote_and_activity.py10
-rw-r--r--askbot/migrations/0095_postize_award_and_repute.py14
-rw-r--r--askbot/migrations/0098_postize_thread_anonanswer_questionview_postrevision.py17
-rw-r--r--askbot/models/__init__.py16
-rw-r--r--askbot/models/post.py2
-rw-r--r--askbot/models/question.py2
-rw-r--r--askbot/skins/common/media/jquery-openid/jquery.openid.js12
-rw-r--r--askbot/skins/common/media/js/editor.js9
-rw-r--r--askbot/skins/common/media/js/post.js88
-rw-r--r--askbot/skins/common/media/js/user.js38
-rw-r--r--askbot/skins/common/templates/authopenid/providers_javascript.html6
-rw-r--r--askbot/skins/common/templates/authopenid/signin.html4
-rw-r--r--askbot/skins/common/templates/question/answer_controls.html97
-rw-r--r--askbot/skins/common/templates/question/answer_vote_buttons.html7
-rw-r--r--askbot/skins/common/templates/question/question_controls.html74
-rw-r--r--askbot/skins/default/media/style/style.css10
-rw-r--r--askbot/skins/default/media/style/style.less6
-rw-r--r--askbot/skins/default/templates/macros.html2
-rw-r--r--askbot/skins/default/templates/question.html2
-rw-r--r--askbot/skins/default/templates/question/answer_card.html2
-rw-r--r--askbot/skins/default/templates/question/javascript.html1
-rw-r--r--askbot/skins/default/templates/question/question_card.html5
-rw-r--r--askbot/skins/default/templates/question/sharing_prompt_phrase.html2
-rw-r--r--askbot/skins/default/templates/question/sidebar.html3
-rw-r--r--askbot/skins/default/templates/question_widget.html2
-rw-r--r--askbot/skins/default/templates/user_profile/user_inbox.html35
-rw-r--r--askbot/tasks.py35
-rw-r--r--askbot/templatetags/extra_filters_jinja.py6
-rw-r--r--askbot/urls.py5
-rw-r--r--askbot/utils/console.py40
-rw-r--r--askbot/utils/url_utils.py14
-rw-r--r--askbot/views/commands.py36
-rw-r--r--askbot/views/readers.py33
-rw-r--r--askbot/views/users.py2
-rw-r--r--askbot/views/writers.py26
54 files changed, 623 insertions, 181 deletions
diff --git a/askbot/deployment/path_utils.py b/askbot/deployment/path_utils.py
index ef260f86..caefa2a9 100644
--- a/askbot/deployment/path_utils.py
+++ b/askbot/deployment/path_utils.py
@@ -154,7 +154,7 @@ def deploy_into(directory, new_project = False, verbosity = 1, context = None):
"""
assert(isinstance(new_project, bool))
if new_project:
- copy_files = ('__init__.py', 'manage.py', 'urls.py')
+ copy_files = ('__init__.py', 'manage.py', 'urls.py', 'django.wsgi')
blank_files = ('__init__.py', 'manage.py')
if verbosity >= 1:
print 'Copying files: '
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index e2056b61..54baa18f 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -10,6 +10,14 @@ Development version (not released yet)
* Fixed the url translation bug (Evgeny)
* Added left sidebar option (Evgeny)
* Added "help" page and links to in the header and the footer (Evgeny)
+* Removed url parameters and the hash fragment from uploaded files -
+ amazon S3 for some reason adds weird expiration parameters (Evgeny)
+* Reduced memory usage in data migrations (Evgeny)
+* Added progress bars to slow data migrations (Evgeny)
+* Added a management command to build_thread_summary_cache (Evgeny)
+* Added a management delete_contextless_badge_award_activities (Evgeny)
+* Fixed a file upload issue in FF and IE found by jerry_gzy (Evgeny)
+* Added test on maximum length of title working for utf-8 text (Evgeny)
0.7.39 (Jan 11, 2012)
---------------------
diff --git a/askbot/doc/source/management-commands.rst b/askbot/doc/source/management-commands.rst
index 1e3a7ac0..b857d6f0 100644
--- a/askbot/doc/source/management-commands.rst
+++ b/askbot/doc/source/management-commands.rst
@@ -78,6 +78,12 @@ The bulk of the management commands fall into this group and will probably be th
| | This data is used to display preferentially real faces |
| | on the main page. |
+---------------------------------+-------------------------------------------------------------+
+| `build_thread_summary_cache` | Rebuilds cache for the question summary snippet. |
++---------------------------------+-------------------------------------------------------------+
+| `delete_contextless_...` | `delete_contextless_badge_award_activities` |
+| | Deletes Activity objects of type badge award where the |
+| | related context object is lost. |
++---------------------------------+-------------------------------------------------------------+
.. _email-related-commands:
diff --git a/askbot/forms.py b/askbot/forms.py
index 08645fcd..fcf43814 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -113,6 +113,22 @@ class TitleField(forms.CharField):
askbot_settings.MIN_TITLE_LENGTH
) % askbot_settings.MIN_TITLE_LENGTH
raise forms.ValidationError(msg)
+ encoded_value = value.encode('utf-8')
+ if len(value) == len(encoded_value):
+ if len(value) > self.max_length:
+ raise forms.ValidationError(
+ _(
+ 'The title is too long, maximum allowed size is '
+ '%d characters'
+ ) % self.max_length
+ )
+ elif encoded_value > self.max_length:
+ raise forms.ValidationError(
+ _(
+ 'The title is too long, maximum allowed size is '
+ '%d bytes'
+ ) % self.max_length
+ )
return value.strip() # TODO: test me
diff --git a/askbot/management/commands/build_thread_summary_cache.py b/askbot/management/commands/build_thread_summary_cache.py
new file mode 100644
index 00000000..854843fe
--- /dev/null
+++ b/askbot/management/commands/build_thread_summary_cache.py
@@ -0,0 +1,10 @@
+from django.core.management.base import NoArgsCommand
+from askbot.models import Thread
+from askbot.utils.console import ProgressBar
+
+class Command(NoArgsCommand):
+ def handle_noargs(self, **options):
+ message = "Rebuilding thread summary cache"
+ count = Thread.objects.count()
+ for thread in ProgressBar(Thread.objects.iterator(), count, message):
+ thread.update_summary_html()
diff --git a/askbot/management/commands/delete_contextless_badge_award_activities.py b/askbot/management/commands/delete_contextless_badge_award_activities.py
new file mode 100644
index 00000000..8116d335
--- /dev/null
+++ b/askbot/management/commands/delete_contextless_badge_award_activities.py
@@ -0,0 +1,20 @@
+from django.core.management.base import NoArgsCommand
+from askbot.utils.console import ProgressBar
+from askbot.models import Activity
+from askbot import const
+
+class Command(NoArgsCommand):
+ def handle_noargs(self, **options):
+ act_type = const.TYPE_ACTIVITY_PRIZE
+ acts = Activity.objects.filter(activity_type = act_type)
+ deleted_count = 0
+ message = "Searching for context-less award activity objects:"
+ for act in ProgressBar(acts.iterator(), acts.count(), message):
+ if act.content_object == None:
+ act.delete()
+ deleted_count += 1
+ if deleted_count:
+ print "%d activity objects deleted" % deleted_count
+ else:
+ print "None found"
+
diff --git a/askbot/migrations/0050_move_qa_revisions_to_postrevision.py b/askbot/migrations/0050_move_qa_revisions_to_postrevision.py
index 36c46551..e4d0ea3b 100644
--- a/askbot/migrations/0050_move_qa_revisions_to_postrevision.py
+++ b/askbot/migrations/0050_move_qa_revisions_to_postrevision.py
@@ -42,10 +42,10 @@ class Migration(DataMigration):
def forwards(self, orm):
# Process revisions
- for qr in orm.QuestionRevision.objects.all():
+ for qr in orm.QuestionRevision.objects.iterator():
self.copy_revision(orm=orm, source_revision=qr)
- for ar in orm.AnswerRevision.objects.all():
+ for ar in orm.AnswerRevision.objects.iterator():
self.copy_revision(orm=orm, source_revision=ar)
diff --git a/askbot/migrations/0053_create_threads_for_questions.py b/askbot/migrations/0053_create_threads_for_questions.py
index e2fe0d40..8c734571 100644
--- a/askbot/migrations/0053_create_threads_for_questions.py
+++ b/askbot/migrations/0053_create_threads_for_questions.py
@@ -3,12 +3,15 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
- for question in orm.Question.objects.all():
+ print "Converting question to threads:"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions):
thread = orm.Thread.objects.create(favourite_count=question.favourite_count)
question.thread = thread
question.save()
diff --git a/askbot/migrations/0057_transplant_answer_count_data.py b/askbot/migrations/0057_transplant_answer_count_data.py
index bd831f66..f83847cd 100644
--- a/askbot/migrations/0057_transplant_answer_count_data.py
+++ b/askbot/migrations/0057_transplant_answer_count_data.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding answer counts to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
thread = question.thread
thread.answer_count = question.answer_count
thread.save()
diff --git a/askbot/migrations/0060_view_count_transplant.py b/askbot/migrations/0060_view_count_transplant.py
index 07fb13d4..e9538655 100644
--- a/askbot/migrations/0060_view_count_transplant.py
+++ b/askbot/migrations/0060_view_count_transplant.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding view counts to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
thread = question.thread
thread.view_count = question.view_count
thread.save()
diff --git a/askbot/migrations/0063_transplant_question_closed_datas.py b/askbot/migrations/0063_transplant_question_closed_datas.py
index b2302d33..15626e48 100644
--- a/askbot/migrations/0063_transplant_question_closed_datas.py
+++ b/askbot/migrations/0063_transplant_question_closed_datas.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Marking closed threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
thread = question.thread
thread.closed = question.closed
diff --git a/askbot/migrations/0066_transplant_accepted_answer_data.py b/askbot/migrations/0066_transplant_accepted_answer_data.py
index 6f5a81a0..f9c28b94 100644
--- a/askbot/migrations/0066_transplant_accepted_answer_data.py
+++ b/askbot/migrations/0066_transplant_accepted_answer_data.py
@@ -5,11 +5,14 @@ from south.v2 import DataMigration
from django.db import models
from askbot.migrations import TERM_YELLOW, TERM_RESET
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding accepted answers to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
thread = question.thread
if question.answer_accepted:
@@ -27,7 +30,8 @@ class Migration(DataMigration):
thread.save()
# Verify data integrity
- for question in orm.Question.objects.all():
+ message = "Checking correctness of accepted answer data"
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
accepted_answers = question.answers.filter(accepted=True)
num_accepted_answers = len(accepted_answers)
diff --git a/askbot/migrations/0069_transplant_last_activity_data.py b/askbot/migrations/0069_transplant_last_activity_data.py
index 5d612254..bcd83ec9 100644
--- a/askbot/migrations/0069_transplant_last_activity_data.py
+++ b/askbot/migrations/0069_transplant_last_activity_data.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding last activity data to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
thread = question.thread
thread.last_activity_at = question.last_activity_at
thread.last_activity_by = question.last_activity_by
diff --git a/askbot/migrations/0072_transplant_tagnames_data.py b/askbot/migrations/0072_transplant_tagnames_data.py
index 3d3fc92a..caa5e6a6 100644
--- a/askbot/migrations/0072_transplant_tagnames_data.py
+++ b/askbot/migrations/0072_transplant_tagnames_data.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding denormalized tags field to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
thread = question.thread
thread.tagnames = question.tagnames
thread.save()
diff --git a/askbot/migrations/0075_transplant_followed_by_data.py b/askbot/migrations/0075_transplant_followed_by_data.py
index 822300ff..06afd155 100644
--- a/askbot/migrations/0075_transplant_followed_by_data.py
+++ b/askbot/migrations/0075_transplant_followed_by_data.py
@@ -3,13 +3,16 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding followers to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
question.thread.followed_by.clear() # just in case someone reversed this migration
- question.thread.followed_by.add(*list(question.followed_by.all()))
+ question.thread.followed_by.add(*list(question.followed_by.iterator()))
if question.followed_by.count() != question.thread.followed_by.count():
raise ValueError("There are Thread instances for which data doesn't match Question!")
diff --git a/askbot/migrations/0079_transplant_favquestions_data.py b/askbot/migrations/0079_transplant_favquestions_data.py
index 351dc7f8..67decb07 100644
--- a/askbot/migrations/0079_transplant_favquestions_data.py
+++ b/askbot/migrations/0079_transplant_favquestions_data.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for fav in orm.FavoriteQuestion.objects.all():
+ message = "Connecting favorite questions to threads"
+ num_favs = orm.FavoriteQuestion.objects.count()
+ for fav in ProgressBar(orm.FavoriteQuestion.objects.iterator(), num_favs, message):
fav.thread = fav.question.thread
fav.save()
diff --git a/askbot/migrations/0082_transplant_title_data.py b/askbot/migrations/0082_transplant_title_data.py
index 6f4a07d6..ccdf1e16 100644
--- a/askbot/migrations/0082_transplant_title_data.py
+++ b/askbot/migrations/0082_transplant_title_data.py
@@ -3,11 +3,14 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
+ message = "Adding titles to threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
question.thread.title = question.title
question.thread.save()
diff --git a/askbot/migrations/0086_transplant_question_tags_data.py b/askbot/migrations/0086_transplant_question_tags_data.py
index a7508229..c2d9fa76 100644
--- a/askbot/migrations/0086_transplant_question_tags_data.py
+++ b/askbot/migrations/0086_transplant_question_tags_data.py
@@ -3,12 +3,15 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- for question in orm.Question.objects.all():
- question.thread.tags.add(*list(question.tags.all()))
+ message = "Linking tag objects with threads"
+ num_questions = orm.Question.objects.count()
+ for question in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
+ question.thread.tags.add(*list(question.tags.iterator()))
if orm.Question.objects.annotate(tag_num=models.Count('tags'), thread_tag_num=models.Count('thread__tags')).exclude(tag_num=models.F('thread_tag_num')).exists():
raise ValueError("There are Thread instances for which data doesn't match Question!")
diff --git a/askbot/migrations/0090_postize_q_a_c.py b/askbot/migrations/0090_postize_q_a_c.py
index f85cbf09..7c85ed21 100644
--- a/askbot/migrations/0090_postize_q_a_c.py
+++ b/askbot/migrations/0090_postize_q_a_c.py
@@ -5,6 +5,7 @@ from south.db import db
from south.v2 import DataMigration
from django.db import models
from django.conf import settings
+from askbot.utils.console import ProgressBar
from askbot.migrations import TERM_RED_BOLD, TERM_GREEN, TERM_RESET
@@ -26,7 +27,9 @@ class Migration(DataMigration):
if 'test' not in sys.argv: # Don't confuse users
print TERM_GREEN, '[DEBUG] Initial Post.id ==', post_id + 1, TERM_RESET
- for q in orm.Question.objects.all():
+ message = "Converting Questions -> Posts"
+ num_questions = orm.Question.objects.count()
+ for q in ProgressBar(orm.Question.objects.iterator(), num_questions, message):
post_id += 1
orm.Post.objects.create(
id=post_id,
@@ -67,7 +70,9 @@ class Migration(DataMigration):
is_anonymous=q.is_anonymous,
)
- for ans in orm.Answer.objects.all():
+ message = "Answers -> Posts"
+ num_answers = orm.Answer.objects.count()
+ for ans in ProgressBar(orm.Answer.objects.iterator(), num_answers, message):
post_id += 1
orm.Post.objects.create(
id=post_id,
@@ -108,7 +113,9 @@ class Migration(DataMigration):
is_anonymous=ans.is_anonymous,
)
- for cm in orm.Comment.objects.all():
+ message = "Comments -> Posts"
+ num_comments = orm.Comment.objects.count()
+ for cm in ProgressBar(orm.Comment.objects.iterator(), num_comments, message):
# Workaround for a strange issue with: http://south.aeracode.org/docs/generics.html
# No need to investigate that as this is as simple as the "proper" way
if (cm.content_type.app_label, cm.content_type.model) == ('askbot', 'question'):
diff --git a/askbot/migrations/0092_postize_vote_and_activity.py b/askbot/migrations/0092_postize_vote_and_activity.py
index 556ef18a..9c77597d 100644
--- a/askbot/migrations/0092_postize_vote_and_activity.py
+++ b/askbot/migrations/0092_postize_vote_and_activity.py
@@ -6,13 +6,15 @@ from south.v2 import DataMigration
from django.db import models
from askbot.migrations import TERM_RED_BOLD, TERM_GREEN, TERM_RESET
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
- # TODO: Speed this up by prefetching all votes ?
- for v in orm.Vote.objects.all():
+ message = "Connecting votes to posts"
+ num_votes = orm.Vote.objects.count()
+ for v in ProgressBar(orm.Vote.objects.iterator(), num_votes, message):
if (v.content_type.app_label, v.content_type.model) == ('askbot', 'question'):
v.voted_post = orm.Post.objects.get(self_question__id=v.object_id)
elif (v.content_type.app_label, v.content_type.model) == ('askbot', 'answer'):
@@ -31,7 +33,9 @@ class Migration(DataMigration):
abandoned_activities = []
- for a in orm.Activity.objects.all():
+ message = "Connecting activity objects to posts"
+ num_activities = orm.Activity.objects.count()
+ for a in ProgressBar(orm.Activity.objects.iterator(), num_activities, message):
# test if content_object for this activity exists - there might be a bunch of "abandoned" activities
#
# NOTE that if activity.content_object is gone then we cannot reliably recover it from activity.question
diff --git a/askbot/migrations/0095_postize_award_and_repute.py b/askbot/migrations/0095_postize_award_and_repute.py
index 0071199c..ea7e7064 100644
--- a/askbot/migrations/0095_postize_award_and_repute.py
+++ b/askbot/migrations/0095_postize_award_and_repute.py
@@ -4,6 +4,7 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
@@ -11,16 +12,23 @@ class Migration(DataMigration):
# ContentType for Post model should be created no later than in migration 0092
ct_post = orm['contenttypes.ContentType'].objects.get(app_label='askbot', model='post')
- for aw in orm.Award.objects.all():
+ message = "Connecting award objects to posts"
+ num_awards = orm.Award.objects.count()
+ for aw in ProgressBar(orm.Award.objects.iterator(), num_awards, message):
ct = aw.content_type
if ct.app_label == 'askbot' and ct.model in ('question', 'answer', 'comment'):
aw.content_type = ct_post
- aw.object_id = orm.Post.objects.get(**{'self_%s__id' % str(ct.model): aw.object_id}).id
+ try:
+ aw.object_id = orm.Post.objects.get(**{'self_%s__id' % str(ct.model): aw.object_id}).id
+ except orm.Post.DoesNotExist:
+ continue
aw.save()
###
- for rp in orm.Repute.objects.all():
+ message = "Connecting repute objects to posts"
+ num_reputes = orm.Repute.objects.count()
+ for rp in ProgressBar(orm.Repute.objects.iterator(), num_reputes, message):
if rp.question:
rp.question_post = orm.Post.objects.get(self_question__id=rp.question.id)
rp.save()
diff --git a/askbot/migrations/0098_postize_thread_anonanswer_questionview_postrevision.py b/askbot/migrations/0098_postize_thread_anonanswer_questionview_postrevision.py
index e253613e..08e62dbb 100644
--- a/askbot/migrations/0098_postize_thread_anonanswer_questionview_postrevision.py
+++ b/askbot/migrations/0098_postize_thread_anonanswer_questionview_postrevision.py
@@ -3,26 +3,35 @@ import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
+from askbot.utils.console import ProgressBar
class Migration(DataMigration):
def forwards(self, orm):
# TODO: Speed this migration up by prefetching data ?
- for thread in orm.Thread.objects.all():
+ message = "Marking accepted answer in threads"
+ num_threads = orm.Thread.objects.count()
+ for thread in ProgressBar(orm.Thread.objects.iterator(), num_threads, message):
if thread.accepted_answer:
thread.accepted_answer_post = orm.Post.objects.get(self_answer__id=thread.accepted_answer.id)
thread.save()
- for qv in orm.QuestionView.objects.all():
+ message = "Connecting question view objects to posts"
+ num_question_views = orm.QuestionView.objects.count()
+ for qv in ProgressBar(orm.QuestionView.objects.iterator(), num_question_views, message):
qv.question_post = orm.Post.objects.get(self_question__id=qv.question.id)
qv.save()
- for aa in orm.AnonymousAnswer.objects.all():
+ message = "Connecting anonymous answers to posts"
+ num_anon_answers = orm.AnonymousAnswer.objects.count()
+ for aa in ProgressBar(orm.AnonymousAnswer.objects.iterator(), num_anon_answers, message):
aa.question_post = orm.Post.objects.get(self_question__id=aa.question.id)
aa.save()
- for rev in orm.PostRevision.objects.all():
+ message = "Connecting post revisions to posts"
+ num_post_revs = orm.PostRevision.objects.count()
+ for rev in ProgressBar(orm.PostRevision.objects.iterator(), num_post_revs, message):
if rev.question:
assert not rev.answer
rev.post = orm.Post.objects.get(self_question__id=rev.question.id)
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index d98d4246..ee2a6f4a 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -36,6 +36,7 @@ from askbot import auth
from askbot.utils.decorators import auto_now_timestamp
from askbot.utils.slug import slugify
from askbot.utils.diff import textDiff as htmldiff
+from askbot.utils.url_utils import strip_path
from askbot.utils import mail
def get_model(model_name):
@@ -488,6 +489,18 @@ def user_assert_can_edit_comment(self, comment = None):
raise django_exceptions.PermissionDenied(error_message)
+def user_can_post_comment(self, parent_post = None):
+ """a simplified method to test ability to comment
+ """
+ if self.reputation >= askbot_settings.MIN_REP_TO_LEAVE_COMMENTS:
+ return True
+ if self == parent_post.author:
+ return True
+ if self.is_administrator_or_moderator():
+ return True
+ return False
+
+
def user_assert_can_post_comment(self, parent_post = None):
"""raises exceptions.PermissionDenied if
user cannot post comment
@@ -2134,6 +2147,7 @@ User.add_to_class('is_following_question', user_is_following_question)
User.add_to_class('mark_tags', user_mark_tags)
User.add_to_class('update_response_counts', user_update_response_counts)
User.add_to_class('can_have_strong_url', user_can_have_strong_url)
+User.add_to_class('can_post_comment', user_can_post_comment)
User.add_to_class('is_administrator', user_is_administrator)
User.add_to_class('is_administrator_or_moderator', user_is_administrator_or_moderator)
User.add_to_class('set_admin_status', user_set_admin_status)
@@ -2279,7 +2293,7 @@ def format_instant_notification_email(
'receiving_user_name': to_user.username,
'content_preview': content_preview,#post.get_snippet()
'update_type': update_type,
- 'post_url': site_url + post.get_absolute_url(),
+ 'post_url': strip_path(site_url) + post.get_absolute_url(),
'origin_post_title': origin_post.thread.title,
'user_subscriptions_url': user_subscriptions_url,
}
diff --git a/askbot/models/post.py b/askbot/models/post.py
index 5cb9708f..1543a438 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -459,7 +459,7 @@ class Post(models.Model):
if self.is_answer():
if not question_post:
question_post = self.thread._question_post()
- return u'%(base)s%(slug)s?answer=%(id)d#answer-container-%(id)d' % {
+ return u'%(base)s%(slug)s?answer=%(id)d#post-id-%(id)d' % {
'base': urlresolvers.reverse('question', args=[question_post.id]),
'slug': django_urlquote(slugify(self.thread.title)),
'id': self.id
diff --git a/askbot/models/question.py b/askbot/models/question.py
index 6c2fa383..6daa3057 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -248,7 +248,7 @@ class ThreadManager(models.Manager):
#print qs.query
- return qs, meta_data
+ return qs.distinct(), meta_data
def precache_view_data_hack(self, threads):
# TODO: Re-enable this when we have a good test cases to verify that it works properly.
diff --git a/askbot/skins/common/media/jquery-openid/jquery.openid.js b/askbot/skins/common/media/jquery-openid/jquery.openid.js
index 29b31b34..249413b9 100644
--- a/askbot/skins/common/media/jquery-openid/jquery.openid.js
+++ b/askbot/skins/common/media/jquery-openid/jquery.openid.js
@@ -193,7 +193,6 @@ $.fn.authenticator = function() {
password_input_fields.hide();
}
reset_password_input_fields();
- $('.error').remove();
if (userIsAuthenticated === false){
email_input_fields.hide();
account_recovery_heading.hide();
@@ -210,13 +209,18 @@ $.fn.authenticator = function() {
}
};
+ var reset_form_and_errors = function(){
+ reset_form();
+ $('.error').remove();
+ }
+
var set_provider_name = function(element){
var provider_name = element.attr('name');
provider_name_input.val(provider_name);
};
var show_openid_input_fields = function(provider_name){
- reset_form();
+ reset_form_and_errors();
var token_name = extra_token_name[provider_name]
if (userIsAuthenticated){
$('#openid-heading').html(
@@ -290,7 +294,7 @@ $.fn.authenticator = function() {
var start_password_login_or_change = function(){
//called upon clicking on one of the password login buttons
- reset_form();
+ reset_form_and_errors();
set_provider_name($(this));
var provider_name = $(this).attr('name');
return setup_password_login_or_change(provider_name);
@@ -370,7 +374,7 @@ $.fn.authenticator = function() {
};
var start_account_recovery = function(){
- reset_form();
+ reset_form_and_errors();
account_recovery_hint.hide();
account_recovery_heading.css('margin-bottom', '0px');
account_recovery_heading.html(account_recovery_prompt_text).show();
diff --git a/askbot/skins/common/media/js/editor.js b/askbot/skins/common/media/js/editor.js
index e580f9f6..2d1f5670 100644
--- a/askbot/skins/common/media/js/editor.js
+++ b/askbot/skins/common/media/js/editor.js
@@ -42,11 +42,11 @@ function ajaxFileUpload(imageUrl, startUploadHandler)
url: askbot['urls']['upload'],
secureuri:false,
fileElementId:'file-upload',
- dataType: 'json',
+ dataType: 'xml',
success: function (data, status)
{
- var fileURL = data['file_url'];
- var error = data['error'];
+ var fileURL = $(data).find('file_url').text();
+ var error = $(data).find('error').text();
if(error != ''){
alert(error);
if (startUploadHandler){
@@ -57,6 +57,7 @@ function ajaxFileUpload(imageUrl, startUploadHandler)
}else{
imageUrl.attr('value', fileURL);
}
+
},
error: function (data, status, e)
{
@@ -71,4 +72,4 @@ function ajaxFileUpload(imageUrl, startUploadHandler)
)
return false;
-}
+};
diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js
index 2f2fbd75..dc3fbfd7 100644
--- a/askbot/skins/common/media/js/post.js
+++ b/askbot/skins/common/media/js/post.js
@@ -291,7 +291,7 @@ var Vote = function(){
var postId;
var questionAuthorId;
var currentUserId;
- var answerContainerIdPrefix = 'answer-container-';
+ var answerContainerIdPrefix = 'post-id-';
var voteContainerId = 'vote-buttons';
var imgIdPrefixAccept = 'answer-img-accept-';
var classPrefixFollow= 'button follow';
@@ -349,8 +349,8 @@ var Vote = function(){
offensiveAnswer:8,
removeOffensiveAnswer:8.5,
removeAllOffensiveAnswer:8.6,
- removeQuestion: 9,
- removeAnswer:10,
+ removeQuestion: 9,//deprecate
+ removeAnswer:10,//deprecate
questionSubscribeUpdates:11,
questionUnsubscribeUpdates:12
};
@@ -520,9 +520,9 @@ var Vote = function(){
Vote.remove_all_offensive(this, VoteType.removeAllOffensiveAnswer);
});
- getremoveQuestionLink().unbind('click').click(function(event){
- Vote.remove(this, VoteType.removeQuestion);
- });
+ //getremoveQuestionLink().unbind('click').click(function(event){
+ // Vote.remove(this, VoteType.removeQuestion);
+ //});
getquestionSubscribeUpdatesCheckbox().unbind('click').click(function(event){
//despeluchar esto
@@ -927,7 +927,7 @@ var Vote = function(){
var do_proceed = false;
if (postType == 'answer'){
- postNode = $('#answer-container-' + postId);
+ postNode = $('#post-id-' + postId);
}
else if (postType == 'question'){
postNode = $('#question-table');
@@ -1126,6 +1126,73 @@ var questionRetagger = function(){
};
}();
+var DeletePostLink = function(){
+ SimpleControl.call(this);
+ this._post_id = null;
+};
+inherits(DeletePostLink, SimpleControl);
+
+DeletePostLink.prototype.setPostId = function(id){
+ this._post_id = id;
+};
+
+DeletePostLink.prototype.getPostId = function(){
+ return this._post_id;
+};
+
+DeletePostLink.prototype.getPostElement = function(){
+ return $('#post-id-' + this.getPostId());
+};
+
+DeletePostLink.prototype.isPostDeleted = function(){
+ return this._post_deleted;
+};
+
+DeletePostLink.prototype.setPostDeleted = function(is_deleted){
+ var post = this.getPostElement();
+ if (is_deleted === true){
+ post.addClass('deleted');
+ this._post_deleted = true;
+ this.getElement().html(gettext('undelete'));
+ } else if (is_deleted === false){
+ post.removeClass('deleted');
+ this._post_deleted = false;
+ this.getElement().html(gettext('delete'));
+ }
+};
+
+DeletePostLink.prototype.getDeleteHandler = function(){
+ var me = this;
+ var post_id = this.getPostId();
+ return function(){
+ var data = {
+ 'post_id': me.getPostId(),
+ //todo rename cancel_vote -> undo
+ 'cancel_vote': me.isPostDeleted() ? true: false
+ };
+ $.ajax({
+ type: 'POST',
+ data: data,
+ dataType: 'json',
+ url: askbot['urls']['delete_post'],
+ cache: false,
+ success: function(data){
+ if (data['success'] == true){
+ me.setPostDeleted(data['is_deleted']);
+ } else {
+ showMessage(me.getElement(), data['message']);
+ }
+ }
+ });
+ };
+};
+
+DeletePostLink.prototype.decorate = function(element){
+ this._element = element;
+ this._post_deleted = this.getPostElement().hasClass('deleted');
+ this.setHandler(this.getDeleteHandler());
+}
+
//constructor for the form
var EditCommentForm = function(){
WrappedElement.call(this);
@@ -1858,6 +1925,13 @@ $(document).ready(function() {
var swapper = new QASwapper();
swapper.decorate($(element));
});
+ $('[id^="post-id-"]').each(function(idx, element){
+ var deleter = new DeletePostLink();
+ //confusingly .question-delete matches the answers too need rename
+ var post_id = element.id.split('-').pop();
+ deleter.setPostId(post_id);
+ deleter.decorate($(element).find('.question-delete'));
+ });
questionRetagger.init();
socialSharing.init();
});
diff --git a/askbot/skins/common/media/js/user.js b/askbot/skins/common/media/js/user.js
index d80adad6..5d205560 100644
--- a/askbot/skins/common/media/js/user.js
+++ b/askbot/skins/common/media/js/user.js
@@ -18,7 +18,7 @@ $(document).ready(function(){
};
var submit = function(id_list, elements, action_type){
- if (action_type == 'delete' || action_type == 'mark_new' || action_type == 'mark_seen'){
+ if (action_type == 'delete' || action_type == 'mark_new' || action_type == 'mark_seen' || action_type == 'remove_flag' || action_type == 'close' || action_type == 'delete_post'){
$.ajax({
type: 'POST',
cache: false,
@@ -27,7 +27,7 @@ $(document).ready(function(){
url: askbot['urls']['manageInbox'],
success: function(response_data){
if (response_data['success'] === true){
- if (action_type == 'delete'){
+ if (action_type == 'delete' || action_type == 'remove_flag' || action_type == 'close' || action_type == 'delete_post'){
elements.remove();
}
else if (action_type == 'mark_new'){
@@ -61,11 +61,35 @@ $(document).ready(function(){
return;
}
}
+ if (action_type == 'close'){
+ msg = ngettext('Close this entry?',
+ 'Close these entries?', data['id_list'].length);
+ if (confirm(msg) === false){
+ return;
+ }
+ }
+ if (action_type == 'remove_flag'){
+ msg = ngettext('Remove all flags on this entry?',
+ 'Remove all flags on these entries?', data['id_list'].length);
+ if (confirm(msg) === false){
+ return;
+ }
+ }
+ if (action_type == 'delete_post'){
+ msg = ngettext('Delete this entry?',
+ 'Delete these entries?', data['id_list'].length);
+ if (confirm(msg) === false){
+ return;
+ }
+ }
submit(data['id_list'], data['elements'], action_type);
};
setupButtonEventHandlers($('#re_mark_seen'), function(){startAction('mark_seen')});
setupButtonEventHandlers($('#re_mark_new'), function(){startAction('mark_new')});
setupButtonEventHandlers($('#re_dismiss'), function(){startAction('delete')});
+ setupButtonEventHandlers($('#re_remove_flag'), function(){startAction('remove_flag')});
+ setupButtonEventHandlers($('#re_close'), function(){startAction('close')});
+ setupButtonEventHandlers($('#re_delete_post'), function(){startAction('delete_post')});
setupButtonEventHandlers(
$('#sel_all'),
function(){
@@ -92,6 +116,16 @@ $(document).ready(function(){
setCheckBoxesIn('#responses .seen', false);
}
);
+
+ 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();
+ }
+ );
});
/**
diff --git a/askbot/skins/common/templates/authopenid/providers_javascript.html b/askbot/skins/common/templates/authopenid/providers_javascript.html
index 0fe72eb3..cd9f56b6 100644
--- a/askbot/skins/common/templates/authopenid/providers_javascript.html
+++ b/askbot/skins/common/templates/authopenid/providers_javascript.html
@@ -43,9 +43,9 @@
<script>
$(document).ready(function(){
if (typeof FB != 'undefined'){
- var ret = FB.init({appId: '{{settings.FACEBOOK_KEY}}', status: true, cookie: true, xfbml: true});
- FB.Event.subscribe('auth.sessionChange', function(response){
- if (response.session) {
+ var ret = FB.init({appId: '{{settings.FACEBOOK_KEY}}', status: true, cookie: true, xfbml: true, oauth: true});
+ FB.Event.subscribe('auth.authResponseChange', function(response){
+ if (response.authResponse) {
$('#signin-form').submit();
}
});
diff --git a/askbot/skins/common/templates/authopenid/signin.html b/askbot/skins/common/templates/authopenid/signin.html
index 7fdbe203..30a576cc 100644
--- a/askbot/skins/common/templates/authopenid/signin.html
+++ b/askbot/skins/common/templates/authopenid/signin.html
@@ -117,6 +117,8 @@
<td><label for="id_new_password">{% trans %}New password{% endtrans %}</label></td>
<td>
{{login_form.new_password}}
+ </td>
+ <td>
<span class="error">{{login_form.new_password.errors[0]}}</span>
</td>
</tr>
@@ -124,6 +126,8 @@
<td><label for="id_new_password_retyped">{% trans %}Please, retype{% endtrans %}</label></td>
<td>
{{login_form.new_password_retyped}}
+ </td>
+ <td>
<span class="error">{{login_form.new_password_retyped.errors[0]}}</span>
</td>
</tr>
diff --git a/askbot/skins/common/templates/question/answer_controls.html b/askbot/skins/common/templates/question/answer_controls.html
index bfc36cea..be50d6f4 100644
--- a/askbot/skins/common/templates/question/answer_controls.html
+++ b/askbot/skins/common/templates/question/answer_controls.html
@@ -1,43 +1,58 @@
-{% set pipe=joiner('<span class="sep">|</span>') %}
-<span class="linksopt">{{ pipe() }}
- <a class="permant-link"
- href="{{ answer.get_absolute_url(question_post=question) }}"
- title="{% trans %}answer permanent link{% endtrans %}">
- {% trans %}permanent link{% endtrans %}
- </a>
- </span>
-
-{% if request.user|can_edit_post(answer) %}{{ pipe() }}
- <span class="action-link"><a class="question-edit" href="{% url edit_answer answer.id %}">{% trans %}edit{% endtrans %}</a></span>
+{#<span class="action-link swap-qa">
+ <a id="swap-question-with-answer-{{answer.id}}">{% trans %}swap with question{% endtrans %}</a>
+</span>uncomment if needed#}
+<span class="action-link">
+ <a class="permant-link"
+ href="{{ answer.get_absolute_url(question_post=question) }}"
+ title="{% trans %}answer permanent link{% endtrans %}">
+ {% trans %}permanent link{% endtrans %}
+ </a>
+</span>
+{% if request.user.is_authenticated() and
+ (
+ request.user == answer.author or
+ request.user.is_administrator_or_moderator()
+ )
+%}
+<span class="action-link delete-post">
+ <a class="question-delete"
+ >{% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a>
+</span>
+<span
+ id="answer-offensive-flag-{{ answer.id }}"
+ class="action-link offensive-flag"
+ title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"
+>
+ <a class="question-flag">{% trans %}flag offensive{% endtrans %}
+ <span class="darkred">{% if answer.offensive_flag_count > 0 %}({{ answer.offensive_flag_count }}){% endif %}</span>
+ </a>
+</span>
+{% if answer.offensive_flag_count > 0 %}
+<span
+ id="answer-offensive-flag-{{ answer.id }}"
+ class="action-link offensive-flag"
+ title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"
+>
+ <a class="question-flag">{% trans %}flag offensive{% endtrans %} ({{ answer.offensive_flag_count }})</a>
+ </a>
+</span>
+<span
+ id="answer-offensive-flag-remove-{{ answer.id }}"
+ class="action-link offensive-flag"
+ title="{% trans %}remove offensive flag{% endtrans %}"
+>
+ <a class="question-flag">{% trans %}remove flag{% endtrans %} ({{ answer.offensive_flag_count }})</a>
+</span>
+{% else %}
+<span
+ id="answer-offensive-flag-{{ answer.id }}"
+ class="action-link offensive-flag"
+ title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"
+>
+ <a class="question-flag">{% trans %}flag offensive{% endtrans %}</a>
+</span>
{% endif %}
-{% if request.user|can_flag_offensive(answer) %}{{ pipe() }}
- <span id="answer-offensive-flag-{{ answer.id }}" class="offensive-flag"
- title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}">
- <a class="question-flag">{% trans %}flag offensive{% endtrans %}</a>
- {% if request.user|can_see_offensive_flags(answer) %}
- <span class="darkred">{% if answer.offensive_flag_count > 0 %}({{ answer.offensive_flag_count }}){% endif %}</span>
- {% endif %}
- </span>
- {% elif request.user|can_remove_flag_offensive(answer)%}{{ pipe() }}
- <span id="answer-offensive-flag-remove-{{ answer.id }}" class="offensive-flag"
- title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}">
- <a class="question-flag">{% trans %}remove flag{% endtrans %}</a>
- {% if request.user|can_see_offensive_flags(answer) %}
- <span class="darkred">{% if answer.offensive_flag_count > 0 %}({{ answer.offensive_flag_count }}){% endif %}</span>
- {% endif %}
- </span>
+<span class="action-link">
+ <a class="question-edit" href="{% url edit_answer answer.id %}">{% trans %}edit{% endtrans %}</a>
+</span>
{% endif %}
-{% if request.user|can_delete_post(answer) %}{{ pipe() }}
- {% spaceless %}
- <span class="action-link">
- <a class="question-delete" id="answer-delete-link-{{answer.id}}">
- {% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a>
- </span>
- {% endspaceless %}
-{% endif %}
-{% if settings.ALLOW_SWAPPING_QUESTION_WITH_ANSWER and request.user.is_authenticated() and request.user.is_administrator_or_moderator() %}{{ pipe() }}
- <span class="action-link">
- <a id="swap-question-with-answer-{{answer.id}}">{% trans %}swap with question{% endtrans %}</a>
- </span>
-{% endif %}
-
diff --git a/askbot/skins/common/templates/question/answer_vote_buttons.html b/askbot/skins/common/templates/question/answer_vote_buttons.html
index 68bff3ed..9097fec2 100644
--- a/askbot/skins/common/templates/question/answer_vote_buttons.html
+++ b/askbot/skins/common/templates/question/answer_vote_buttons.html
@@ -5,7 +5,12 @@
{% else %}
src="{{'/images/vote-accepted.png'|media}}"
{% endif %}
- {% if request.user == question.author or (request.user.is_authenticated() and (request.user.is_moderator() or request.user.is_administrator())) %}
+ {% if request.user.is_authenticated() and
+ (
+ request.user == question.author or
+ request.user.is_administrator_or_moderator()
+ )
+ %}
alt="{% trans %}mark this answer as correct (click again to undo){% endtrans %}"
title="{% trans %}mark this answer as correct (click again to undo){% endtrans %}"
{% else %}
diff --git a/askbot/skins/common/templates/question/question_controls.html b/askbot/skins/common/templates/question/question_controls.html
index 5658d559..4710559d 100644
--- a/askbot/skins/common/templates/question/question_controls.html
+++ b/askbot/skins/common/templates/question/question_controls.html
@@ -1,39 +1,43 @@
-{% set pipe=joiner('<span class="sep">|</span>') %}
-{% if request.user|can_edit_post(question) %}{{ pipe() }}
- <a class="question-edit" href="{% url edit_question question.id %}">{% trans %}edit{% endtrans %}</a>
-{% endif %}
-{% if request.user|can_retag_question(question) %}{{ pipe() }}
- <a id="retag" class="question-retag"href="{% url retag_question question.id %}">{% trans %}retag{% endtrans %}</a>
- <script type="text/javascript">
- var retagUrl = "{% url retag_question question.id %}";
- </script>
-{% endif %}
-{% if thread.closed %}
- {% if request.user|can_reopen_question(question) %}{{ pipe() }}
+{% if request.user.is_authenticated() and
+ (
+ request.user == question.author or
+ request.user.is_administrator_or_moderator()
+ )
+%}
+ <a
+ id="question-delete-link-{{question.id}}"
+ class="question-delete"
+ >{% if question.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a>
+ {% if thread.closed %}
<a class="question-close" href="{% url reopen question.id %}">{% trans %}reopen{% endtrans %}</a>
- {% endif %}
-{% else %}
- {% if request.user|can_close_question(question) %}{{ pipe() }}
+ {% else %}
<a class="question-close" href="{% url close question.id %}">{% trans %}close{% endtrans %}</a>
{% endif %}
-{% endif %}
-{% if request.user|can_flag_offensive(question) %}{{ pipe() }}
- <span id="question-offensive-flag-{{ question.id }}" class="offensive-flag"
- title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}">
- <a class="question-flag">{% trans %}flag offensive{% endtrans %}</a>
- {% if request.user|can_see_offensive_flags(question) %}
- <span class="darkred">{% if question.offensive_flag_count > 0 %}({{ question.offensive_flag_count }}){% endif %}</span>
- {% endif %}
- </span>
- {% elif request.user|can_remove_flag_offensive(question)%}{{ pipe() }}
- <span id="question-offensive-flag-remove-{{ question.id }}" class="offensive-flag"
- title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}">
- <a class="question-flag">{% trans %}remove flag{% endtrans %}</a>
- {% if request.user|can_see_offensive_flags(question) %}
- <span class="darkred">{% if question.offensive_flag_count > 0 %}({{ question.offensive_flag_count }}){% endif %}</span>
- {% endif %}
- </span>
-{% endif %}
-{% if request.user|can_delete_post(question) %}{{ pipe() }}
- <a id="question-delete-link-{{question.id}}" class="question-delete">{% if question.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a>
+ {% if question.offensive_flag_count > 0 %}
+ <span
+ id="question-offensive-flag-{{ question.id }}" class="offensive-flag"
+ title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"
+ >
+ <a class="question-flag">{% trans %}flag offensive{% endtrans %} {{ question.offensive_flag_count }})</a>
+ </span>
+ <span
+ id="question-offensive-flag-remove-{{ question.id }}"
+ class="offensive-flag"
+ title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"
+ >
+ <a class="question-flag">{% trans %}remove flag{% endtrans %} ({{ question.offensive_flag_count }})</a>
+ </span>
+ {% else %}
+ <span
+ id="question-offensive-flag-{{ question.id }}" class="offensive-flag"
+ title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"
+ >
+ <a class="question-flag">{% trans %}flag offensive{% endtrans %}</a>
+ </span>
+ {% endif %}
+ <script type="text/javascript">
+ var retagUrl = "{% url retag_question question.id %}";
+ </script>
+ <a id="retag" class="question-retag"href="{% url retag_question question.id %}">{% trans %}retag{% endtrans %}</a>
+ <a class="question-edit" href="{% url edit_question question.id %}">{% trans %}edit{% endtrans %}</a>
{% endif %}
diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css
index d52c4f11..737dcdd2 100644
--- a/askbot/skins/default/media/style/style.css
+++ b/askbot/skins/default/media/style/style.css
@@ -3153,3 +3153,13 @@ pre.prettyprint {
#leading-sidebar {
float: left;
}
+
+a.re_expand{
+ color: #616161;
+ text-decoration:none;
+}
+
+a.re_expand .re_content{
+ display:none;
+ margin-left:77px;
+} \ No newline at end of file
diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less
index 7b564d8a..e8e5a5d8 100644
--- a/askbot/skins/default/media/style/style.less
+++ b/askbot/skins/default/media/style/style.less
@@ -1623,8 +1623,8 @@ ul#related-tags li {
margin-bottom:8px;
a {
- color: #777;
- padding: 0px 3px 3px 22px;
+ color: #777;
+ padding: 0px 7px 3px 18px;
cursor: pointer;
border: none;
font-size:12px;
@@ -1653,7 +1653,7 @@ ul#related-tags li {
.post-controls, .answer-controls{
.question-delete{
background: url(../images/delete.png) no-repeat center left;
- padding-left:16px;
+ padding-left:11px;
}
.question-flag{
background: url(../images/flag.png) no-repeat center left;
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index dcbe7874..af0826ab 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -317,7 +317,7 @@ for the purposes of the AJAX comment editor #}
{% endfor %}
</div>
<div class="controls">
- {% set can_post = user|can_post_comment(post) %}
+ {% set can_post = user.is_authenticated() and user.can_post_comment(post) %}
{% if show_post == post and show_comment %}
{% if show_comment_position > max_comments %}
{{
diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html
index 33c0e11f..b2462faf 100644
--- a/askbot/skins/default/templates/question.html
+++ b/askbot/skins/default/templates/question.html
@@ -6,7 +6,7 @@
{% endblock %}
{% block keywords %}{{thread.tagname_meta_generator()}}{% endblock %}
{% block forestyle %}
- <link rel="canonical" href="{{settings.APP_URL}}{{question.get_absolute_url()}}" />
+ <link rel="canonical" href="{{settings.APP_URL|strip_path}}{{question.get_absolute_url()}}" />
<link rel="stylesheet" type="text/css" href="{{'/js/wmd/wmd.css'|media}}" />
{% endblock %}
{% block content %}
diff --git a/askbot/skins/default/templates/question/answer_card.html b/askbot/skins/default/templates/question/answer_card.html
index 60317559..d71131a8 100644
--- a/askbot/skins/default/templates/question/answer_card.html
+++ b/askbot/skins/default/templates/question/answer_card.html
@@ -4,7 +4,7 @@
<a class="old_answer_id_anchor" name="{{ answer.old_answer_id }}"></a>
{% endif %}
<div
- id="answer-container-{{ answer.id }}"
+ id="post-id-{{ answer.id }}"
class="{{ macros.answer_classes(answer, question) }}">
<div class="vote-buttons">
{# ==== START: question/answer_vote_buttons.html ==== #}
diff --git a/askbot/skins/default/templates/question/javascript.html b/askbot/skins/default/templates/question/javascript.html
index 9c8e7fc6..a5a53e39 100644
--- a/askbot/skins/default/templates/question/javascript.html
+++ b/askbot/skins/default/templates/question/javascript.html
@@ -16,6 +16,7 @@
askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}';
askbot['urls']['swap_question_with_answer'] = '{% url swap_question_with_answer %}';
askbot['urls']['upvote_comment'] = '{% url upvote_comment %}';
+ askbot['urls']['delete_post'] = '{% url delete_post %}';
askbot['messages']['addComment'] = '{% trans %}add comment{% endtrans %}';
{% if settings.SAVE_COMMENT_ON_ENTER %}
askbot['settings']['saveCommentOnEnter'] = true;
diff --git a/askbot/skins/default/templates/question/question_card.html b/askbot/skins/default/templates/question/question_card.html
index ff4ada1d..7077a8d1 100644
--- a/askbot/skins/default/templates/question/question_card.html
+++ b/askbot/skins/default/templates/question/question_card.html
@@ -1,4 +1,3 @@
-
<div class="vote-buttons">
{# ==== BEGIN: question/question_vote_buttons.html ==== #}
{% include "question/question_vote_buttons.html" %}
@@ -7,13 +6,13 @@
{% include "question/share_buttons.html" %}
{# ==== END: question/share_buttons.html ==== #}
</div>
-<div class="question-content">
+<div id="post-id-{{question.id}}" class="question-content{% if question.deleted %} deleted{% endif %}">
<h1><a href="{{ question.get_absolute_url() }}">{{ thread.get_title(question)|escape }}</a></h1>
{% include "question/question_tags.html" %}
{# ==== END: question/question_tags.html" #}
- <div id="question-table" {% if question.deleted %}class="deleted"{%endif%}>
+ <div id="question-table">
<div class="question-body">
<div class="post-update-info-container">
{# ==== START: "question/question_author_info.html" #}
diff --git a/askbot/skins/default/templates/question/sharing_prompt_phrase.html b/askbot/skins/default/templates/question/sharing_prompt_phrase.html
index f7bd20af..2e68d1f3 100644
--- a/askbot/skins/default/templates/question/sharing_prompt_phrase.html
+++ b/askbot/skins/default/templates/question/sharing_prompt_phrase.html
@@ -1,4 +1,4 @@
-{% set question_url=settings.APP_URL+question.get_absolute_url()|urlencode %}
+{% set question_url=(settings.APP_URL|strip_path + question.get_absolute_url())|urlencode %}
<h2 class="share-question">{% trans %}Know someone who can answer? Share a <a href="{{ question_url }}">link</a> to this question via{% endtrans %}
{% if settings.ENABLE_SHARING_TWITTER %}{{ macros.share(site = 'twitter', site_label = 'Twitter') }},{% endif %}
{% if settings.ENABLE_SHARING_FACEBOOK %}{{ macros.share(site = 'facebook', site_label = 'Facebook') }},{% endif %}
diff --git a/askbot/skins/default/templates/question/sidebar.html b/askbot/skins/default/templates/question/sidebar.html
index bc6a58c9..08c043a6 100644
--- a/askbot/skins/default/templates/question/sidebar.html
+++ b/askbot/skins/default/templates/question/sidebar.html
@@ -37,8 +37,6 @@
</p>
</div>
</div>
-{% cache 0 "questions_tags" questions_tags question.id language_code %}
-
{% if settings.SIDEBAR_QUESTION_SHOW_META %}
<div class="box statsWidget">
@@ -55,7 +53,6 @@
</p>
</div>
{% endif %}
-{% endcache %}
{% if similar_threads.data and settings.SIDEBAR_QUESTION_SHOW_RELATED %}
{#% cache 1800 "related_questions" related_questions question.id language_code %#}
diff --git a/askbot/skins/default/templates/question_widget.html b/askbot/skins/default/templates/question_widget.html
index 65ee8b64..9d32294b 100644
--- a/askbot/skins/default/templates/question_widget.html
+++ b/askbot/skins/default/templates/question_widget.html
@@ -11,7 +11,7 @@
<div id="container">
<ul>
{% for thread in threads %}
- <li><a href="{{settings.APP_URL}}{{ thread.get_absolute_url() }}">
+ <li><a href="{{settings.APP_URL|strip_path}}{{ thread.get_absolute_url() }}">
{{ thread.title|escape }}</a></li>
{% endfor %}
</ul>
diff --git a/askbot/skins/default/templates/user_profile/user_inbox.html b/askbot/skins/default/templates/user_profile/user_inbox.html
index e7e3dbfe..f70f1884 100644
--- a/askbot/skins/default/templates/user_profile/user_inbox.html
+++ b/askbot/skins/default/templates/user_profile/user_inbox.html
@@ -56,6 +56,18 @@ inbox_section - forum|flags
<button id="re_dismiss">{% trans %}dismiss{% endtrans %}</button>
</div>
{% endif %}
+ {% if inbox_section == 'flags' %}
+ <div id="re_tools">
+ <strong>{% trans %}select:{% endtrans %}</strong>
+ <a id="sel_all">{% trans %}all{% endtrans %}</a> |
+ <a id="sel_seen">{% trans %}seen{% endtrans %}</a> |
+ <a id="sel_new">{% trans %}new{% endtrans %}</a> |
+ <a id="sel_none">{% trans %}none{% endtrans %}</a><br />
+ <button id="re_remove_flag">{% trans %}remove flags{% endtrans %}</button>
+ <button id="re_close">{% trans %}close{% endtrans %}</button>
+ <button id="re_delete_post">{% trans %}delete post{% endtrans %}</button>
+ </div>
+ {% endif %}
<div id="responses">
{% for response in responses %}
<div class="response-parent">
@@ -63,7 +75,7 @@ inbox_section - forum|flags
<strong>"{{ response.response_title.strip()|escape}}"</strong>
</p>
<div id="re_{{response.id}}" class="re{% if response.is_new %} new highlight{% else %} seen{% endif %}">
- {% if inbox_section == 'forum' %}<input type="checkbox" />{% endif %}
+ <input type="checkbox" />
<div class="face">
{{ macros.gravatar(response.user, 48) }}
</div>
@@ -71,13 +83,20 @@ inbox_section - forum|flags
<a style="text-decoration:none;" href="{{ response.response_url }}">
{{ response.response_type }}
({{ response.timestamp|diff_date(True) }}):<br/>
- {{ response.response_snippet}}
+ {% if inbox_section != 'flags' %}
+ {{ response.response_snippet }}
+ {% endif %}
</a>
+ {% if inbox_section == 'flags' %}
+ <a class="re_expand" href="{{ response.response_url }}">
+ <div class="re_snippet">{{ response.response_snippet }}</div>
+ <div class="re_content">{{ response.response_content }}</div></a>
+ {% endif %}
</div>
{% if response.nested_responses %}
{%for nested_response in response.nested_responses %}
<div id="re_{{nested_response.id}}" class="re{% if nested_response.is_new %} new highlight{% else %} seen{% endif %}">
- {% if inbox_section == 'forum' %}<input type="checkbox" />{% endif %}
+ <input type="checkbox" />
<div class="face">
{{ macros.gravatar(nested_response.user, 48) }}
</div>
@@ -85,8 +104,15 @@ inbox_section - forum|flags
<a style="text-decoration:none;" href="{{ nested_response.response_url }}">
{{ nested_response.response_type }}
({{ nested_response.timestamp|diff_date(True) }}):<br/>
- {{ nested_response.response_snippet}}
+ {% if inbox_section != 'flags' %}
+ {{ nested_response.response_snippet }}
+ {% endif %}
</a>
+ {% if inbox_section == 'flags' %}
+ <a class="re_expand" href="{{ nested_response.response_url }}">
+ <div class="re_snippet">{{ nested_response.response_snippet }}</div>
+ <div class="re_content">{{ nested_response.response_content }}</div></a>
+ {% endif %}
</div>
{%endfor%}
{%endif%}
@@ -96,7 +122,6 @@ inbox_section - forum|flags
</div>
{% endblock %}
{% block userjs %}
- <script type="text/javascript" src="{{'/js/user.js'|media}}"></script>
<script type="text/javascript">
var askbot = askbot || {};
askbot['urls'] = askbot['urls'] || {};
diff --git a/askbot/tasks.py b/askbot/tasks.py
index fefe99f5..634befb9 100644
--- a/askbot/tasks.py
+++ b/askbot/tasks.py
@@ -22,15 +22,15 @@ import traceback
from django.contrib.contenttypes.models import ContentType
from celery.decorators import task
-from askbot.models import Activity
-from askbot.models import User
+from askbot.models import Activity, Post, Thread, User
from askbot.models import send_instant_notifications_about_activity_in_post
+from askbot.models.badges import award_badges_signal
# TODO: Make exceptions raised inside record_post_update_celery_task() ...
# ... propagate upwards to test runner, if only CELERY_ALWAYS_EAGER = True
# (i.e. if Celery tasks are not deferred but executed straight away)
-@task(ignore_results = True)
+@task(ignore_result = True)
def record_post_update_celery_task(
post_id,
post_content_type_id,
@@ -152,3 +152,32 @@ def record_post_update(
post = post,
recipients = notification_subscribers,
)
+
+@task(ignore_result = True)
+def record_question_visit(
+ question_post_id = None,
+ user_id = None,
+ update_view_count = False):
+ """celery task which records question visit by a person
+ updates view counter, if necessary,
+ and awards the badges associated with the
+ question visit
+ """
+ #1) maybe update the view count
+ question_post = Post.objects.get(id = question_post_id)
+ if update_view_count:
+ question_post.thread.increase_view_count()
+
+ #2) question view count per user and clear response displays
+ user = User.objects.get(id = user_id)
+ if user.is_authenticated():
+ #get response notifications
+ user.visit_question(question_post)
+
+ #3) send award badges signal for any badges
+ #that are awarded for question views
+ award_badges_signal.send(None,
+ event = 'view_question',
+ actor = user,
+ context_object = question_post,
+ )
diff --git a/askbot/templatetags/extra_filters_jinja.py b/askbot/templatetags/extra_filters_jinja.py
index 52180da5..b7fbc5f0 100644
--- a/askbot/templatetags/extra_filters_jinja.py
+++ b/askbot/templatetags/extra_filters_jinja.py
@@ -14,6 +14,7 @@ from askbot.conf import settings as askbot_settings
from django.conf import settings as django_settings
from askbot.skins import utils as skin_utils
from askbot.utils import functions
+from askbot.utils import url_utils
from askbot.utils.slug import slugify
from askbot.shims.django_shims import ResolverMatch
@@ -35,6 +36,11 @@ def absolutize_urls_func(text):
absolutize_urls = register.filter(absolutize_urls_func)
@register.filter
+def strip_path(url):
+ """removes path part of the url"""
+ return url_utils.strip_path(url)
+
+@register.filter
def clean_login_url(url):
"""pass through, unless user was originally on the logout page"""
try:
diff --git a/askbot/urls.py b/askbot/urls.py
index 640cb51e..1ab3ea5d 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -130,6 +130,11 @@ urlpatterns = patterns('',
name = 'upvote_comment'
),
url(#ajax only
+ r'^post/delete/$',
+ views.commands.delete_post,
+ name = 'delete_post'
+ ),
+ url(#ajax only
r'^post_comments/$',
views.writers.post_comments,
name='post_comments'
diff --git a/askbot/utils/console.py b/askbot/utils/console.py
index 496bbd65..fe6ad29e 100644
--- a/askbot/utils/console.py
+++ b/askbot/utils/console.py
@@ -74,3 +74,43 @@ def print_progress(elapsed, total, nowipe = False):
in-place"""
output = '%6.2f%%' % (100 * float(elapsed)/float(total))
print_action(output, nowipe)
+
+class ProgressBar(object):
+ """A wrapper for an iterator, that prints
+ a progress bar along the way of iteration
+ """
+ def __init__(self, iterable, length, message = ''):
+ self.iterable = iterable
+ self.length = length
+ self.counter = float(0)
+ self.barlen = 60
+ self.progress = ''
+ if message and length > 0:
+ print message
+
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+
+ try:
+ result = self.iterable.next()
+ except StopIteration:
+ if self.length > 0:
+ sys.stdout.write('\n')
+ raise
+
+ sys.stdout.write('\b'*len(self.progress))
+
+ if self.length < self.barlen:
+ sys.stdout.write('-'*(self.barlen/self.length))
+ elif int(self.counter) % (self.length / self.barlen) == 0:
+ sys.stdout.write('-')
+
+ self.progress = ' %.2f%%' % (100 * (self.counter/self.length))
+ sys.stdout.write(self.progress)
+ sys.stdout.flush()
+
+ self.counter += 1
+ return result
diff --git a/askbot/utils/url_utils.py b/askbot/utils/url_utils.py
index 0ebce394..6027d096 100644
--- a/askbot/utils/url_utils.py
+++ b/askbot/utils/url_utils.py
@@ -1,6 +1,18 @@
+import urlparse
from django.core.urlresolvers import reverse
from django.conf import settings
+def strip_path(url):
+ """srips path, params and hash fragments of the url"""
+ purl = urlparse.urlparse(url)
+ return urlparse.urlunparse(
+ urlparse.ParseResult(
+ purl.scheme,
+ purl.netloc,
+ '', '', '', ''
+ )
+ )
+
def get_login_url():
"""returns internal login url if
django_authopenid is used, or
@@ -27,6 +39,6 @@ def get_logout_redirect_url():
if 'askbot.deps.django_authopenid' in settings.INSTALLED_APPS:
return reverse('logout')
elif hasattr(settings, 'LOGOUT_REDIRECT_URL'):
- return settigs.LOGOUT_REDIRECT_URL
+ return settings.LOGOUT_REDIRECT_URL
else:
return reverse('index')
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 7db27ef2..b95143b0 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -41,7 +41,7 @@ def manage_inbox(request):
post_data = simplejson.loads(request.raw_post_data)
if request.user.is_authenticated():
activity_types = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY
- activity_types += (const.TYPE_ACTIVITY_MENTION, )
+ activity_types += (const.TYPE_ACTIVITY_MENTION, const.TYPE_ACTIVITY_MARK_OFFENSIVE,)
user = request.user
memo_set = models.ActivityAuditStatus.objects.filter(
id__in = post_data['memo_list'],
@@ -56,6 +56,18 @@ def manage_inbox(request):
memo_set.update(status = models.ActivityAuditStatus.STATUS_NEW)
elif action_type == 'mark_seen':
memo_set.update(status = models.ActivityAuditStatus.STATUS_SEEN)
+ elif action_type == 'remove_flag':
+ for memo in memo_set:
+ request.user.flag_post(post = memo.activity.content_object, cancel_all = True)
+ elif action_type == 'close':
+ for memo in memo_set:
+ if memo.activity.content_object.post_type == "question":
+ request.user.close_question(question = memo.activity.content_object, reason = 7)
+ memo.delete()
+ elif action_type == 'delete_post':
+ for memo in memo_set:
+ request.user.delete_post(post = memo.activity.content_object)
+ memo.delete()
else:
raise exceptions.PermissionDenied(
_('Oops, apologies - there was some error')
@@ -584,6 +596,28 @@ def upvote_comment(request):
raise ValueError
return {'score': comment.score}
+@csrf.csrf_exempt
+@decorators.ajax_only
+@decorators.post_only
+def delete_post(request):
+ if request.user.is_anonymous():
+ raise exceptions.PermissionDenied(_('Please sign in to delete/restore posts'))
+ form = forms.VoteForm(request.POST)
+ if form.is_valid():
+ post_id = form.cleaned_data['post_id']
+ post = get_object_or_404(
+ models.Post,
+ post_type__in = ('question', 'answer'),
+ id = post_id
+ )
+ if form.cleaned_data['cancel_vote']:
+ request.user.restore_post(post)
+ else:
+ request.user.delete_post(post)
+ else:
+ raise ValueError
+ return {'is_deleted': post.deleted}
+
#askbot-user communication system
@csrf.csrf_exempt
def read_message(request):#marks message a read
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index cccfce67..a6f65e28 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -30,7 +30,6 @@ from askbot.utils.diff import textDiff as htmldiff
from askbot.forms import AnswerForm, ShowQuestionForm
from askbot import models
from askbot import schedules
-from askbot.models.badges import award_badges_signal
from askbot.models.tag import Tag
from askbot import const
from askbot.utils import functions
@@ -428,7 +427,9 @@ def question(request, id):#refactor - long subroutine. display question body, an
# TODO: Add unit test to catch the bug where precache_comments() is called above (before) reordering the accepted answer to the top
#Post.objects.precache_comments(for_posts=[question_post] + answers, visitor=request.user)
- if thread.accepted_answer: # Put the accepted answer to front
+ if thread.accepted_answer and thread.accepted_answer.deleted == False:
+ #Put the accepted answer to front
+ #the second check is for the case when accepted answer is deleted
answers.remove(thread.accepted_answer)
answers.insert(0, thread.accepted_answer)
@@ -467,11 +468,9 @@ def question(request, id):#refactor - long subroutine. display question body, an
last_seen = request.session['question_view_times'].get(question_post.id, None)
- updated_when, updated_who = thread.get_last_update_info()
-
- if updated_who != request.user:
+ if thread.last_activity_by != request.user:
if last_seen:
- if last_seen < updated_when:
+ if last_seen < thread.last_activity_at:
update_view_count = True
else:
update_view_count = True
@@ -479,21 +478,13 @@ def question(request, id):#refactor - long subroutine. display question body, an
request.session['question_view_times'][question_post.id] = \
datetime.datetime.now()
- if update_view_count:
- thread.increase_view_count()
-
- #2) question view count per user and clear response displays
- if request.user.is_authenticated():
- #get response notifications
- request.user.visit_question(question_post)
-
- #3) send award badges signal for any badges
- #that are awarded for question views
- award_badges_signal.send(None,
- event = 'view_question',
- actor = request.user,
- context_object = question_post,
- )
+ #2) run the slower jobs in a celery task
+ from askbot import tasks
+ tasks.record_question_visit.delay(
+ question_post_id = question_post.id,
+ user_id = request.user.id,
+ update_view_count = update_view_count
+ )
paginator_data = {
'is_paginated' : (objects_list.count > const.ANSWERS_PAGE_SIZE),
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 28561bf4..b38a54c8 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -597,6 +597,7 @@ def user_responses(request, user, context):
'response_type': memo.activity.get_activity_type_display(),
'response_id': memo.activity.question.id,
'nested_responses': [],
+ 'response_content': memo.activity.content_object.html,
}
response_list.append(response)
@@ -617,6 +618,7 @@ def user_responses(request, user, context):
last_response_index = i
response_list = filtered_response_list
+
response_list.sort(lambda x,y: cmp(y['timestamp'], x['timestamp']))
filtered_response_list = list()
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 9de14517..7ebb1991 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -12,6 +12,7 @@ import random
import sys
import tempfile
import time
+import urlparse
from django.core.files.storage import get_storage_class
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
@@ -99,16 +100,29 @@ def upload(request):#ajax upload file to a question or answer
if error == '':
result = 'Good'
file_url = file_storage.url(new_file_name)
+ parsed_url = urlparse.urlparse(file_url)
+ file_url = urlparse.urlunparse(
+ urlparse.ParseResult(
+ parsed_url.scheme,
+ parsed_url.netloc,
+ parsed_url.path,
+ '', '', ''
+ )
+ )
else:
result = ''
file_url = ''
- data = simplejson.dumps({
- 'result': result,
- 'error': error,
- 'file_url': file_url
- })
- return HttpResponse(data, mimetype = 'application/json')
+ #data = simplejson.dumps({
+ # 'result': result,
+ # 'error': error,
+ # 'file_url': file_url
+ #})
+ #return HttpResponse(data, mimetype = 'application/json')
+ xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>"
+ xml = xml_template % (result, error, file_url)
+
+ return HttpResponse(xml, mimetype="application/xml")
def __import_se_data(dump_file):
"""non-view function that imports the SE data