summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/conf/sidebar_question.py20
-rw-r--r--askbot/doc/source/changelog.rst1
-rw-r--r--askbot/management/commands/fix_answer_counts.py5
-rw-r--r--askbot/management/commands/fix_question_tags.py30
-rw-r--r--askbot/management/commands/fix_revisionless_posts.py7
-rw-r--r--askbot/models/question.py2
-rw-r--r--askbot/models/tag.py4
-rw-r--r--askbot/skins/common/media/js/post.js5
-rw-r--r--askbot/skins/common/media/js/utils.js4
-rw-r--r--askbot/skins/default/media/style/style.less5
-rw-r--r--askbot/skins/default/templates/macros.html16
-rw-r--r--askbot/skins/default/templates/question.html3
-rw-r--r--askbot/skins/default/templates/tags.html1
-rw-r--r--askbot/skins/default/templates/user_profile/user_stats.html1
-rw-r--r--askbot/tests/db_api_tests.py17
-rw-r--r--askbot/tests/page_load_tests.py19
-rw-r--r--askbot/tests/utils.py12
-rw-r--r--askbot/views/commands.py3
18 files changed, 120 insertions, 35 deletions
diff --git a/askbot/conf/sidebar_question.py b/askbot/conf/sidebar_question.py
index 4416823d..bb71be7e 100644
--- a/askbot/conf/sidebar_question.py
+++ b/askbot/conf/sidebar_question.py
@@ -6,21 +6,35 @@ from askbot.deps.livesettings import ConfigurationGroup
from askbot.deps.livesettings import values
from django.utils.translation import ugettext as _
from askbot.conf.super_groups import CONTENT_AND_UI
-SIDEBAR_QUESTION = ConfigurationGroup(
+SIDEBAR_QUESTION = ConfigurationGroup(#shitty name - why sidebar?
'SIDEBAR_QUESTION',
- _('Question page sidebar'),
+ _('Question page banners and sidebar'),
super_group = CONTENT_AND_UI
)
settings.register(
values.LongStringValue(
SIDEBAR_QUESTION,
+ 'QUESTION_PAGE_TOP_BANNER',
+ description = _('Top banner'),
+ default = '',
+ help_text = _(
+ 'When using this option, please '
+ 'use the HTML validation service to make sure that '
+ 'your input is valid and works well in all browsers.'
+ )
+ )
+)
+
+settings.register(
+ values.LongStringValue(
+ SIDEBAR_QUESTION,
'SIDEBAR_QUESTION_HEADER',
description = _('Custom sidebar header'),
default = '',
help_text = _(
'Use this area to enter content at the TOP of the sidebar'
- 'in HTML format. When using this option '
+ 'in HTML format. When using this option '
'(as well as the sidebar footer), please '
'use the HTML validation service to make sure that '
'your input is valid and works well in all browsers.'
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
index a15ad406..f975b83c 100644
--- a/askbot/doc/source/changelog.rst
+++ b/askbot/doc/source/changelog.rst
@@ -9,6 +9,7 @@ Development version
to help prevent user profile spam (Evgeny)
* Added a function to create a custom user profile tab,
the feature requires access to the server (Evgeny)
+* Added optional top banner to the question page (Evgeny)
0.7.43 (May 14, 2012)
---------------------
diff --git a/askbot/management/commands/fix_answer_counts.py b/askbot/management/commands/fix_answer_counts.py
index 959e37b6..9f22422e 100644
--- a/askbot/management/commands/fix_answer_counts.py
+++ b/askbot/management/commands/fix_answer_counts.py
@@ -23,6 +23,5 @@ class Command(NoArgsCommand):
"""function that handles the command job
"""
self.remove_save_signals()
- questions = models.Question.objects.all()
- for question in questions:
- question.thread.update_answer_count()
+ for thread in models.Thread.objects.all():
+ thread.update_answer_count()
diff --git a/askbot/management/commands/fix_question_tags.py b/askbot/management/commands/fix_question_tags.py
index 9858e397..d575e651 100644
--- a/askbot/management/commands/fix_question_tags.py
+++ b/askbot/management/commands/fix_question_tags.py
@@ -39,33 +39,33 @@ class Command(NoArgsCommand):
transaction.commit()
#go through questions and fix tag records on each
- questions = models.Question.objects.all()
+ threads = models.Thread.objects.all()
checked_count = 0
found_count = 0
- total_count = questions.count()
+ total_count = threads.count()
print "Searching for questions with inconsistent tag records:",
- for question in questions:
- tags = question.thread.tags.all()
- denorm_tag_set = set(question.get_tag_names())
- norm_tag_set = set(question.thread.tags.values_list('name', flat=True))
+ for thread in threads:
+ tags = thread.tags.all()
+ denorm_tag_set = set(thread.get_tag_names())
+ norm_tag_set = set(thread.tags.values_list('name', flat=True))
if norm_tag_set != denorm_tag_set:
- if question.last_edited_by:
- user = question.last_edited_by
- timestamp = question.last_edited_at
+ if thread.last_edited_by:
+ user = thread.last_edited_by
+ timestamp = thread.last_edited_at
else:
- user = question.author
- timestamp = question.added_at
+ user = thread.author
+ timestamp = thread.added_at
- tagnames = forms.TagNamesField().clean(question.tagnames)
+ tagnames = forms.TagNamesField().clean(thread.tagnames)
- question.thread.update_tags(
+ thread.update_tags(
tagnames = tagnames,
user = user,
timestamp = timestamp
)
- question.thread.tagnames = tagnames
- question.thread.save()
+ thread.tagnames = tagnames
+ thread.save()
found_count += 1
transaction.commit()
diff --git a/askbot/management/commands/fix_revisionless_posts.py b/askbot/management/commands/fix_revisionless_posts.py
index 92c03425..9535bef3 100644
--- a/askbot/management/commands/fix_revisionless_posts.py
+++ b/askbot/management/commands/fix_revisionless_posts.py
@@ -7,11 +7,11 @@ from django.db.models import signals, Count
from askbot import models
from askbot import const
-def fix_revisionless_posts(post_class, post_name):
+def fix_revisionless_posts(post_class):
posts = post_class.objects.annotate(
rev_count = Count('revisions')
).filter(rev_count = 0)
- print 'have %d corrupted %ss' % (len(posts), post_name)
+ print 'have %d corrupted posts' % len(posts)
for post in posts:
post.add_revision(
author = post.author,
@@ -39,5 +39,4 @@ class Command(NoArgsCommand):
"""function that handles the command job
"""
self.remove_save_signals()
- fix_revisionless_posts(models.Question, 'question')
- fix_revisionless_posts(models.Answer, 'answer')
+ fix_revisionless_posts(models.Post)
diff --git a/askbot/models/question.py b/askbot/models/question.py
index b3d755f5..1729b531 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -74,6 +74,7 @@ class ThreadManager(models.Manager):
by_email = False,
email_address = None
):
+ """creates new thread"""
# TODO: Some of this code will go to Post.objects.create_new
thread = super(
@@ -786,6 +787,7 @@ class Thread(models.Model):
return False
def retag(self, retagged_by=None, retagged_at=None, tagnames=None, silent=False):
+ """changes thread tags"""
if None in (retagged_by, retagged_at, tagnames):
raise Exception('arguments retagged_at, retagged_by and tagnames are required')
diff --git a/askbot/models/tag.py b/askbot/models/tag.py
index 5a83c67c..858db2e6 100644
--- a/askbot/models/tag.py
+++ b/askbot/models/tag.py
@@ -118,7 +118,9 @@ class GroupTagManager(BaseQuerySetManager):
#replace spaces with dashes
group_name = clean_group_name(group_name)
try:
- tag = self.get(name = group_name)
+ #iexact is important!!! b/c we don't want case variants
+ #of tags
+ tag = self.get(name__iexact = group_name)
except self.model.DoesNotExist:
tag = self.model(name = group_name, created_by = user)
tag.save()
diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js
index f5ef7c9d..58f2436d 100644
--- a/askbot/skins/common/media/js/post.js
+++ b/askbot/skins/common/media/js/post.js
@@ -1062,10 +1062,11 @@ var questionRetagger = function(){
var tags_str = '';
links.each(function(index, element){
if (index === 0){
- tags_str = $(element).html();
+ //this is pretty bad - we should use Tag.getName()
+ tags_str = $(element).attr('data-tag-name');
}
else {
- tags_str += ' ' + $(element).html();
+ tags_str += ' ' + $(element).attr('data-tag-name');
}
});
return tags_str;
diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js
index d5ce1c2d..d04a3cdb 100644
--- a/askbot/skins/common/media/js/utils.js
+++ b/askbot/skins/common/media/js/utils.js
@@ -987,7 +987,9 @@ Tag.prototype.decorate = function(element){
this._delete_icon.decorate(del);
}
this._inner_element = this._element.find('.tag');
- this._name = this.decodeTagName($.trim(this._inner_element.html()));
+ this._name = this.decodeTagName(
+ $.trim(this._inner_element.attr('data-tag-name'))
+ );
if (this._title !== null){
this._inner_element.attr('title', this._title);
}
diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less
index 87f1f4c8..343204fe 100644
--- a/askbot/skins/default/media/style/style.less
+++ b/askbot/skins/default/media/style/style.less
@@ -3167,6 +3167,11 @@ ul.post-tags li {
ul.post-retag {
margin-bottom:0px;
margin-left:5px;
+ input {
+ width: 400px;
+ height: 1.5em;
+ margin: 3px 0 0 -3px;
+ }
}
#question-controls .tags {
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index e8d8246b..485713aa 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -200,7 +200,8 @@ poor design of the data or methods on data objects #}
search_state = None,
css_class = None,
tag_css_class = None,
- tag_html_tag = 'li'
+ tag_html_tag = 'li',
+ truncate_long_tags = False
)
-%}
<ul {% if id %}id="{{ id }}"{% endif %}
@@ -214,7 +215,8 @@ poor design of the data or methods on data objects #}
deletable = deletable,
is_link = make_links,
search_state = search_state,
- html_tag = tag_html_tag
+ html_tag = tag_html_tag,
+ truncate_long_tag = False
)}}
{% endfor %}
{% endif %}
@@ -276,7 +278,8 @@ poor design of the data or methods on data objects #}
css_class = None,
search_state = None,
html_tag = 'div',
- extra_content = ''
+ extra_content = '',
+ truncate_long_tag = False
)
-%}
{% if not search_state %} {# get empty SearchState() if there's none; CAUTION: for some reason this doesn't work inside `spaceless` tag below! #}
@@ -291,7 +294,12 @@ poor design of the data or methods on data objects #}
title="{% trans %}see questions tagged '{{ tag }}'{% endtrans %}"
{% endif %}
rel="tag"
- >{{ tag|replace('*', '&#10045;')|truncate(20,True)}}</{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %}>
+ data-tag-name="{{ tag|replace('*', '&#10045;')|escape }}"
+ >{% if truncate_long_tag -%}
+ {{ tag|replace('*', '&#10045;')|truncate(17, True) }}
+ {%- else -%}
+ {{ tag|replace('*', '&#10045;') }}
+ {%- endif %}</{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %}>
{% if deletable %}
<div class="delete-icon"
{% if delete_link_title %}
diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html
index bd48bd54..bb74db33 100644
--- a/askbot/skins/default/templates/question.html
+++ b/askbot/skins/default/templates/question.html
@@ -157,6 +157,9 @@
</script>
{% endblock %}
{% block content %}
+ <div>
+ {{ settings.QUESTION_PAGE_TOP_BANNER }}
+ </div>
{% if is_cacheable %}
{% cache long_time "thread-content-html" thread.id %}
{% include "question/content.html" %}
diff --git a/askbot/skins/default/templates/tags.html b/askbot/skins/default/templates/tags.html
index 6b89bdba..007388af 100644
--- a/askbot/skins/default/templates/tags.html
+++ b/askbot/skins/default/templates/tags.html
@@ -40,6 +40,7 @@
{{ macros.tag_widget(
tag = tag.name,
html_tag = 'div',
+ truncate_long_tag = True,
extra_content = '<span class="tag-number">&#215; ' ~
tag.used_count|intcomma ~ '</span>'
)
diff --git a/askbot/skins/default/templates/user_profile/user_stats.html b/askbot/skins/default/templates/user_profile/user_stats.html
index b125589c..177df214 100644
--- a/askbot/skins/default/templates/user_profile/user_stats.html
+++ b/askbot/skins/default/templates/user_profile/user_stats.html
@@ -90,6 +90,7 @@
tag.name,
html_tag = 'div',
search_state = search_state,
+ truncate_long_tag = True,
extra_content =
'<span class="tag-number">&#215; ' ~
tag.user_tag_usage_count|intcomma ~
diff --git a/askbot/tests/db_api_tests.py b/askbot/tests/db_api_tests.py
index 1f3d3b9b..3a0c9582 100644
--- a/askbot/tests/db_api_tests.py
+++ b/askbot/tests/db_api_tests.py
@@ -15,6 +15,9 @@ from askbot.conf import settings as askbot_settings
import datetime
class DBApiTests(AskbotTestCase):
+ """tests methods on User object,
+ that were added for askbot
+ """
def setUp(self):
self.create_user()
@@ -161,7 +164,8 @@ class DBApiTests(AskbotTestCase):
matches = models.Post.objects.get_questions().get_by_text_query("database'")
self.assertTrue(len(matches) == 1)
-class UserLikeTests(AskbotTestCase):
+class UserLikeTagTests(AskbotTestCase):
+ """tests for user liking and disliking tags"""
def setUp(self):
self.create_user()
self.question = self.post_question(tags = 'one two three')
@@ -387,3 +391,14 @@ class CommentTests(AskbotTestCase):
self.other_user.upvote(comment, cancel = True)
comment = models.Post.objects.get_comments().get(id = self.comment.id)
self.assertEquals(comment.score, 0)
+
+class TagAndGroupTests(AskbotTestCase):
+ def setUp(self):
+ self.u1 = self.create_user('u1')
+
+ def test_group_cannot_create_case_variant_tag(self):
+ self.post_question(user = self.u1, tags = 'one two three')
+ models.Tag.group_tags.get_or_create(user = self.u1, group_name = 'One')
+ tag_one = models.Tag.objects.filter(name__iexact = 'one')
+ self.assertEqual(tag_one.count(), 1)
+ self.assertEqual(tag_one[0].name, 'one')
diff --git a/askbot/tests/page_load_tests.py b/askbot/tests/page_load_tests.py
index ebfba0c3..e3e699a7 100644
--- a/askbot/tests/page_load_tests.py
+++ b/askbot/tests/page_load_tests.py
@@ -67,7 +67,9 @@ class PageLoadTestCase(AskbotTestCase):
def setUp(self):
self.old_cache = cache.cache
- cache.cache = DummyCache('', {}) # Disable caching (to not interfere with production cache, not sure if that's possible but let's not risk it)
+ #Disable caching (to not interfere with production cache,
+ #not sure if that's possible but let's not risk it)
+ cache.cache = DummyCache('', {})
def tearDown(self):
cache.cache = self.old_cache # Restore caching
@@ -610,3 +612,18 @@ class QuestionPageRedirectTests(AskbotTestCase):
#point to a non-existing comment
resp = self.client.get(url, data={'comment': 100301})
self.assertRedirects(resp, expected_url = self.q.get_absolute_url())
+
+class CommandViewTests(AskbotTestCase):
+ def test_get_tag_wiki_text_succeeds(self):
+ tag1 = self.create_tag('tag1')
+ response = self.client.get(
+ reverse('load_tag_wiki_text'),
+ data = {'tag_id': tag1.id}
+ )
+ self.assertEqual(response.status_code, 200)
+
+ def test_get_tag_wiki_text_fails(self):
+ tag1 = self.create_tag('tag1')
+ response = self.client.get(reverse('load_tag_wiki_text'))
+ self.assertEqual(response.status_code, 400)#bad request
+
diff --git a/askbot/tests/utils.py b/askbot/tests/utils.py
index 8395b1ca..4bc69ac4 100644
--- a/askbot/tests/utils.py
+++ b/askbot/tests/utils.py
@@ -174,6 +174,18 @@ class AskbotTestCase(TestCase):
timestamp = timestamp
)
+ def create_tag(self, tag_name, user = None):
+ """creates a user, b/c it is necessary"""
+ if user is None:
+ try:
+ user = models.User.objects.get(username = 'tag_creator')
+ except models.User.DoesNotExist:
+ user = self.create_user('tag_creator')
+
+ tag = models.Tag(created_by = user, name = tag_name)
+ tag.save()
+ return tag
+
def post_comment(
self,
user = None,
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index ec535aef..83f62b34 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -485,6 +485,9 @@ def get_tag_list(request):
@decorators.get_only
def load_tag_wiki_text(request):
"""returns text of the tag wiki in markdown format"""
+ if 'tag_id' not in request.GET:
+ return HttpResponse('', status = 400)#bad request
+
tag = get_object_or_404(models.Tag, id = request.GET['tag_id'])
tag_wiki_text = getattr(tag.tag_wiki, 'text', '').strip()
return HttpResponse(tag_wiki_text, mimetype = 'text/plain')