diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-04-10 10:50:02 -0400 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-04-10 10:50:02 -0400 |
commit | c5a44b521650dd35c9092308ab30f29c5e3a8f43 (patch) | |
tree | e64430be885e3de7492e947d1f6b2523d56e979a | |
parent | 72c356b993771063e080c7cb47b8fc23a964dc1a (diff) | |
download | askbot-c5a44b521650dd35c9092308ab30f29c5e3a8f43.tar.gz askbot-c5a44b521650dd35c9092308ab30f29c5e3a8f43.tar.bz2 askbot-c5a44b521650dd35c9092308ab30f29c5e3a8f43.zip |
intermediate broken commit
27 files changed, 416 insertions, 176 deletions
diff --git a/forum/const.py b/forum/const.py index 6f6086f0..dd85bb2e 100755 --- a/forum/const.py +++ b/forum/const.py @@ -58,7 +58,7 @@ DEFAULT_QUESTIONS_PAGE_SIZE = 30 PAGE_SIZES = (10,30,50) UNANSWERED_MEANING_LIST = ('NO_ANSWERS','NO_UPVOTED_ANSWERS','NO_ACCEPTED_ANSWERS') -UNANSWERED_MEANING = 'NO_ANSWERS' +UNANSWERED_MEANING = 'NO_ACCEPTED_ANSWERS' assert(UNANSWERED_MEANING in UNANSWERED_MEANING_LIST) #todo: diff --git a/forum/forms.py b/forum/forms.py index c32ce6c0..2c2df738 100755 --- a/forum/forms.py +++ b/forum/forms.py @@ -136,6 +136,7 @@ class AdvancedSearchForm(forms.Form): reset_tags = forms.BooleanField(required=False) reset_author = forms.BooleanField(required=False) reset_query = forms.BooleanField(required=False) + start_over = forms.BooleanField(required=False) tags = forms.CharField(max_length=256,required=False) author = forms.IntegerField(required=False) page_size = forms.ChoiceField(choices=const.PAGE_SIZES, required=False) @@ -188,6 +189,8 @@ class AdvancedSearchForm(forms.Form): del self.cleaned_data['reset_author'] if self.cleaned_data['reset_query'] == False: del self.cleaned_data['reset_query'] + if self.cleaned_data['start_over'] == False: + del self.cleaned_data['start_over'] if self.cleaned_data['author'] is None: del self.cleaned_data['author'] if self.cleaned_data['page'] is None: diff --git a/forum/middleware/view_log.py b/forum/middleware/view_log.py index 6f59568a..213292fe 100644 --- a/forum/middleware/view_log.py +++ b/forum/middleware/view_log.py @@ -1,8 +1,16 @@ import logging from django.conf import settings from forum.views.readers import questions as questions_view -from forum.views.commands import vote as vote_view -from django.views.static import serve as django_serve_view +from forum.views.commands import vote +from django.views.static import serve +from forum.views.writers import delete_comment, question_comments, answer_comments +from forum.views.readers import question, question_revisions, answer_revisions + +#todo: the list is getting bigger and bigger - maybe there is a better way to +#trigger reset of sarch state? +IGNORED_VIEWS = (serve, vote, delete_comment, + question_comments, answer_comments, + question, question_revisions, answer_revisions) class ViewLog(object): """must be modified only in this middlware @@ -36,17 +44,21 @@ class ViewLogMiddleware(object): def process_view(self, request, view_func, view_args, view_kwargs): if view_func == questions_view: view_str = 'questions' - elif view_func in (django_serve_view, vote_view): + elif view_func in IGNORED_VIEWS: return - elif settings.DEBUG == True: + else: + view_str = view_func.__name__ + if view_str == 'wrap': + print str(view_func.__module__)# == 'forum.utils.decorators': + return + + if settings.DEBUG == True: #todo: dependency! - from debug_toolbar.views import debug_media_view + from debug_toolbar.views import debug_media as debug_media_view if view_func == debug_media_view: return else: view_str = view_func.__name__ - else: - view_str = view_func.__name__ if request.user.is_authenticated(): user_name = request.user.username diff --git a/forum/models/__init__.py b/forum/models/__init__.py index 2349c9e3..191f66d3 100755 --- a/forum/models/__init__.py +++ b/forum/models/__init__.py @@ -5,6 +5,8 @@ from meta import Vote, Comment, FlaggedItem from user import Activity, ValidationHash, EmailFeedSetting, AuthKeyUserAssociation from repute import Badge, Award, Repute from django.core.urlresolvers import reverse +from forum.search.indexer import create_fulltext_indexes +from django.db.models.signals import post_syncdb import re from base import * @@ -440,6 +442,7 @@ tags_updated.connect(record_update_tags, sender=Question) post_save.connect(record_favorite_question, sender=FavoriteQuestion) user_updated.connect(record_user_full_updated, sender=User) user_logged_in.connect(post_stored_anonymous_content) +post_syncdb.connect(create_fulltext_indexes) Question = Question QuestionRevision = QuestionRevision diff --git a/forum/models/question.py b/forum/models/question.py index 98b50490..aae99da2 100755 --- a/forum/models/question.py +++ b/forum/models/question.py @@ -10,6 +10,7 @@ import datetime from django.conf import settings from django.utils.datastructures import SortedDict from forum.models.tag import MarkedTag +from django.db.models import Q markdowner = Markdown(html4tags=True) @@ -77,7 +78,8 @@ class QuestionManager(models.Manager): #return metadata meta_data = {} if tag_selector: - qs = qs.filter(tags__name__in = tag_selector) + for tag in tag_selector: + qs = qs.filter(tags__name = tag) if search_query: qs = qs.filter(deleted=False).extra( @@ -101,9 +103,9 @@ class QuestionManager(models.Manager): #user contributed questions & answers if author_selector: try: - u = User.objects.get(username=author_selector) - qs = qs.filter(Q(author=u) | Q(answers__author=u)) - meta_data['author_name'] = author_selector + u = User.objects.get(id=int(author_selector)) + qs = qs.filter(Q(author=u, deleted=False) | Q(answers__author=u, answers__deleted=False)) + meta_data['author_name'] = u.username except User.DoesNotExist: meta_data['author_name'] = None @@ -155,6 +157,7 @@ class QuestionManager(models.Manager): if orderby: #relevance will be ignored here qs = qs.order_by(orderby) + qs = qs.distinct() return qs, meta_data def update_tags(self, question, tagnames, user): diff --git a/forum/search/indexer.py b/forum/search/indexer.py new file mode 100644 index 00000000..c7c45c59 --- /dev/null +++ b/forum/search/indexer.py @@ -0,0 +1,9 @@ +from django.conf import settings +from django.db import connection + +def create_fulltext_indexes(): + if settings.DATABASE_ENGINE == 'mysql': + cursor = connection.cursor() + cursor.execute('ALTER TABLE question ADD FULLTEXT (title, text, tagnames)') + cursor.execute('ALTER TABLE answer ADD FULLTEXT (title, text, tagnames)') + diff --git a/forum/search/state_manager.py b/forum/search/state_manager.py index b36c5e53..4b3772b6 100644 --- a/forum/search/state_manager.py +++ b/forum/search/state_manager.py @@ -51,12 +51,13 @@ class SearchState(object): setattr(self, key, new_value) self.reset_page() - def update_from_user_input(self,input): + def update_from_user_input(self,input, raw_input = {}): #todo: this function will probably not #fit the case of multiple parameters entered at the same tiem - print ','.join(input.keys()) + if 'start_over' in input: + self.reset() + if 'page' in input: - print input['page'] self.page = input['page'] #special case - on page flip no other input is accepted return @@ -76,7 +77,10 @@ class SearchState(object): if 'tags' in input: if self.tags: old_tags = self.tags.copy() - self.tags.union(input['tags']) + print 'old tags %s' % str(old_tags) + print 'new tags %s' % str(input['tags']) + self.tags = self.tags.union(input['tags']) + print 'combined %s' % str(self.tags) if self.tags != old_tags: self.reset_page() else: @@ -97,11 +101,7 @@ class SearchState(object): return if 'reset_query' in input: - if self.query: - self.query = None - self.reset_page() - if self.sort == 'relevant': - self.reset_sort() + self.reset_query() return self.update_value('author',input) @@ -109,6 +109,9 @@ class SearchState(object): if 'query' in input: self.update_value('query',input) self.sort = 'relevant' + elif 'search' in raw_input:#a case of use nulling search query by hand + self.reset_query() + return if 'sort' in input: @@ -120,6 +123,13 @@ class SearchState(object): def reset_page(self): self.page = 1 + def reset_query(self): + if self.query: + self.query = None + self.reset_page() + if self.sort == 'relevant': + self.reset_sort() + def reset_sort(self): self.sort = const.DEFAULT_POST_SORT_METHOD diff --git a/forum/skins/default/media/style/style.css b/forum/skins/default/media/style/style.css index 8315839d..81c6965e 100755 --- a/forum/skins/default/media/style/style.css +++ b/forum/skins/default/media/style/style.css @@ -204,7 +204,6 @@ blockquote { background-color: #F5F5F5; } -/*页面布局*/ #wrapper { width: 960px; margin: auto; @@ -340,28 +339,56 @@ blockquote { padding-right: 0px; } -/*搜索栏*/ #searchBar { width: 958px; background-color: #888a85; /*#e9b96e;*/ border: 1px solid #aaaaaa; - padding: 4px 0 0 0; + padding: 4px 0 5px 5px; } - -/* #B02B2C */ -#searchBar .content { +#fakeSearchBar { + width: 958px; + height: 4px; + background-color: #888a85; /*#e9b96e;*/ + border: 1px solid #aaaaaa; } #searchBar .searchInput { - font-size: 13px; - height: 18px; - width: 400px; + font-size: 24px; + line-height: 24px; + height: 36px; + width: 620px; + margin: 0px; + padding: 5px 0 0 5px; +} + +#searchBar .searchInputCancelable { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 570px; + padding: 5px 0 0 5px; + margin: 0px; } #searchBar .searchBtn { - font-size: 14px; - height: 26px; - width: 80px; + font-size: 20px; + color: #666666; + height: 40px; + line-height: 22px; + text-align: center; + margin-top:1px; + padding-bottom: 4px; +} + +#searchBar .cancelSearchBtn { + font-size: 20px; + color: #666666; + height: 40px; + width: 40px; + line-height: 22px; + padding-bottom: 4px; + margin-top:1px; + text-align: center; } #searchBar .options { @@ -552,6 +579,10 @@ blockquote { font-weight: 800; } +.evenMore a { + text-decoration: underline; +} + .questions-count { font-size: 32px; font-family: sans-serif; @@ -1503,6 +1534,10 @@ span.form-error { width: 100%; } +#id_title { + width: 100%; +} + .wmd-preview { margin-top: 10px; padding: 6px; @@ -2539,3 +2574,20 @@ p.signup_p { color:red; padding:5px; } + +.search-result-summary { + font-weight: bold; + font-size:18px; + line-height:30px; + margin:0px 0px 0px 5px; + padding:0px; +} +.search-tips { + font-size:12px; + line-height:12px; + margin:0 0 5px 5px; + padding:0px; +} +.search-tips a { + text-decoration: underline; +} diff --git a/forum/skins/default/templates/base.html b/forum/skins/default/templates/base.html index 1018da50..fe5a95a3 100644 --- a/forum/skins/default/templates/base.html +++ b/forum/skins/default/templates/base.html @@ -2,6 +2,7 @@ <!-- template base.html --> {% load extra_filters %} {% load extra_tags %} +{% load smart_if %} {% load i18n %} <html xmlns="http://www.w3.org/1999/xhtml"> <head> @@ -36,7 +37,19 @@ }); </script> {% endif %} - + {% if active_tab != "tags" and active_tab != "users" %} + <script type="text/javascript"> + $('#nav_ask').click( + function(){ + alert('hullo'); + var starting_title = $('#keywords').attr('value'); + alert('tittle is ' + starting_title); + window.location.href = $(this).attr('href') + '?' + + starting_title; + } + ); + </script> + {% endif %} {% block forejs %} {% endblock %} </head> diff --git a/forum/skins/default/templates/book.html b/forum/skins/default/templates/book.html index 8574fa73..528b800d 100644 --- a/forum/skins/default/templates/book.html +++ b/forum/skins/default/templates/book.html @@ -122,7 +122,7 @@ </h3> <div class="tags"> {% for tag in question.tagname_list %} - <a href="{% url tag_questions tag|urlencode %}" title="{% "see questions tagged with" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a> + <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a> {% endfor %} </div> <div class="started"> diff --git a/forum/skins/default/templates/header.html b/forum/skins/default/templates/header.html index aaf19874..efc0d8f2 100644 --- a/forum/skins/default/templates/header.html +++ b/forum/skins/default/templates/header.html @@ -1,5 +1,6 @@ <!-- template header.html --> {% load extra_tags %} +{% load smart_if %} {% load i18n %} <div id="roof"> <div id="navBar"> @@ -15,53 +16,75 @@ </div> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> - <td width="23%"> - <div id="logo"> - <a href="{% url index %}"> - <img src="{% media "/media/images/logo.png" %}" title="{% trans "back to home page" %}" alt="{{settings.APP_TITLE}} logo"/> - </a> - </div> - </td> - <td width="77%" valign="bottom"> - <div class="nav"> - <a id="nav_questions" href="{% url questions %}" >{% trans "questions" %}</a> - <a id="nav_tags" href="{% url tags %}">{% trans "tags" %}</a> - <a id="nav_users" href="{% url users %}">{% trans "users" %}</a> - {% if settings.BOOKS_ON %} - <a id="nav_books" href="{% url books %}">{% trans "books" %}</a> - {% endif %} - <a id="nav_badges" href="{% url badges %}">{% trans "badges" %}</a> - {% comment %} - <a id="nav_unanswered" href="{% url unanswered %}">{% trans "unanswered questions" %}</a> - {% endcomment %} - <div class="focus"> - <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a> - </div> + <td width="23%"> + <div id="logo"> + <a href="{% url questions %}?start_over=true"><img + src="{% media "/media/images/logo.png" %}" title="{% trans "back to home page" %}" alt="{{settings.APP_TITLE}} logo"/></a> + </div> + </td> + <td width="77%" valign="bottom"> + <div class="nav"> + <a id="nav_questions" href="{% url questions %}" >{% trans "questions" %}</a> + <a id="nav_tags" href="{% url tags %}">{% trans "tags" %}</a> + <a id="nav_users" href="{% url users %}">{% trans "users" %}</a> + {% if settings.BOOKS_ON %} + <a id="nav_books" href="{% url books %}">{% trans "books" %}</a> + {% endif %} + <a id="nav_badges" href="{% url badges %}">{% trans "badges" %}</a> + <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a> + {% comment %} + <a id="nav_unanswered" href="{% url unanswered %}">{% trans "unanswered questions" %}</a> + <div class="focus"> + <a id="nav_ask" href="{% url ask %}" class="special">{% trans "ask a question" %}</a> </div> - - </td> + {% endcomment %} + </div> + </td> </tr> </table> </div> + {% if active_tab != "ask" %} <div id="searchBar"> - <table width="100%" border="0" cellpadding="0" cellspacing="0" class="content"> - <tr> - <td align="center" valign="middle"> - <form action="{% url search %}" method="get"> - <div> - <input type="text" class="searchInput" value="{{ keywords }}" name="q" id="keywords" /> - <input type="submit" name="Submit" value="{% trans "search" %}" class="searchBtn" /> - </div> - <div class="options"> - <input id="type-question" type="radio" value="question" name="t" - checked="checked" /><label for="type-question">{% trans "questions" %}</label> - <input id="type-tag" type="radio" value="tag" name="t" /><label for="type-tag">{% trans "tags" %}</label> - <input id="type-user" type="radio" value="user" name="t" /><label for="type-user">{% trans "users" %}</label> - </div> - </form> - </td> - </tr> - </table> + {% comment %}url action depends on which tab is active{% endcomment %} + <form + {% if active_tab == "tags" or active_tab == "users" %} + action="{% url search %}" + {% else %} + action="{% url questions %}" + {% endif %} + method="get"> + {% comment %} class was searchInput {% endcomment %} + <input + {% if query %} + class="searchInputCancelable" + {% else %} + class="searchInput" + {% endif %} + type="text" + value="{{ query|default_if_none:"" }}" + name="query" + id="keywords"/> + {% if active_tab == "tags" %} + <input type="hidden" name="t" value="tag"/> + {% else %} + {% if active_tab == "users" %} + <input type="hidden" name="t" value="user"/> + {% endif %} + {% endif %} + {% if query %}{% comment %}query is only defined by questions view{% endcomment %} + <input type="button" + value="x" + name="reset_query" + {% comment %}todo - make sure it works on Enter keypress{% endcomment %} + onclick="window.location.href='{% url questions %}?reset_query=true'" + value="true" + class="cancelSearchBtn"/> + {% endif %} + <input type="submit" value="{% trans "search" %}" name="search" class="searchBtn" default /> + </form> </div> + {% else %} + <div id="fakeSearchBar"></div> + {% endif %} </div> <!-- end template header.html --> diff --git a/forum/skins/default/templates/index.html b/forum/skins/default/templates/index.html index 8a885dd4..b90d788a 100644 --- a/forum/skins/default/templates/index.html +++ b/forum/skins/default/templates/index.html @@ -57,11 +57,12 @@ {% cache 60 recent_tags %}
{% for tag in tags %}
<a rel="tag"
- title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>
+ title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}"
+ href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }}</a>
{% endfor %}
{% endcache %}
</div>
- <div class="more"><a href="{% url tags %}">{% trans "popular tags" %} </a> </div>
+ <div class="more"><a href="{% url tags %}">{% trans "see all tags" %}</a> </div>
</div>
</div>
{% if awards %}
diff --git a/forum/skins/default/templates/index_.html b/forum/skins/default/templates/index_.html index 5e4cf533..8ba169a7 100644 --- a/forum/skins/default/templates/index_.html +++ b/forum/skins/default/templates/index_.html @@ -60,7 +60,7 @@ <div class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}' {% trans "using tags" %}" rel="tag">{{ tag }}</a>
+ <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
</div>
@@ -87,7 +87,8 @@ <div class="tags">
{% for tag in tags %}
<a rel="tag"
- title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>
+ title="{% blocktrans with tag.name as tagname %}see questions tagged '{{tagname}}'{% endblocktrans %}"
+ href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }}</a>
{% endfor %}
</div>
<div class="more"><a href="{% url tags %}">{% trans "popular tags" %} »</a> </div>
diff --git a/forum/skins/default/templates/question.html b/forum/skins/default/templates/question.html index 1c542c8b..c3564a34 100644 --- a/forum/skins/default/templates/question.html +++ b/forum/skins/default/templates/question.html @@ -128,10 +128,12 @@ {{ question.html|safe }}
</div>
<div id="question-controls" class="post-controls">
+ {% comment %}todo: here we have important case to reset search state{% endcomment %}
<div id="question-tags" class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url tag_questions tag|urlencode %}" class="post-tag"
- title="{% blocktrans with tag as tagname %}see questions tagged '{{ tagname }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
+ <a href="{% url questions %}?tags={{tag|urlencode}}&start_over=true"
+ class="post-tag"
+ title="{% blocktrans %}see questions tagged '{{tag}}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
{% joinitems using '<span class="action-link-separator">|</span>' %}
@@ -474,9 +476,10 @@ </p>
<p class="tags" >
{% for tag in tags %}
- <a href="{% url tag_questions tag.name|urlencode %}"
- title="{% trans "see questions tagged"%}'{{tag.name}}'{% trans "using tags" %}"
- rel="tag">{{ tag.name }}</a> <span class="tag-number">×{{ tag.used_count|intcomma }}</span><br/>
+ <a href="{% url questions %}?tags={{tag.name|urlencode}}&start_over=true"
+ title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{tag_name}}'{% endblocktrans %}"
+ rel="tag">{{ tag.name }}</a>
+ <span class="tag-number">×{{ tag.used_count|intcomma }}</span><br/>
{% endfor %}
</p>
<p>
diff --git a/forum/skins/default/templates/question_list.html b/forum/skins/default/templates/question_list.html index 53633691..38ac254a 100644 --- a/forum/skins/default/templates/question_list.html +++ b/forum/skins/default/templates/question_list.html @@ -16,7 +16,7 @@ </div>
<div class="tags">
{% for tag in question.tagname_list %}
- <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}' {% trans "using tags" %}" rel="tag">{{ tag }}</a>
+ <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{%endblocktrans %}" rel="tag">{{ tag }}</a>
{% endfor %}
</div>
</div>
diff --git a/forum/skins/default/templates/question_summary_list_roll.html b/forum/skins/default/templates/question_summary_list_roll.html index 57685d6d..f2432a24 100644 --- a/forum/skins/default/templates/question_summary_list_roll.html +++ b/forum/skins/default/templates/question_summary_list_roll.html @@ -49,7 +49,7 @@ <div class="tags"> {% for tag in question.tagname_list %} - <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag">{{ tag }}</a> + <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a> {% endfor %} </div> </div> diff --git a/forum/skins/default/templates/questions.html b/forum/skins/default/templates/questions.html index 0a7c0c96..03ccc324 100644 --- a/forum/skins/default/templates/questions.html +++ b/forum/skins/default/templates/questions.html @@ -48,7 +48,7 @@ </div><br/>
{% endcomment %}
<div class="tabsC">
- <span class="label">{% trans "Pick:" %}</span>
+ <span class="label">{% trans "In:" %}</span>
<a id="all" class="off" href="?scope=all" title="{% trans "see all questions" %}">{% trans "all" %}</a>
<a id="unanswered" class="off" href="?scope=unanswered" title="{% trans "see unanswered questions" %}">{% trans "unanswered" %}</a>
{% if request.user.is_authenticated %}
@@ -134,20 +134,90 @@ {% endif %}
</div>
</div>
+{% if questions_count > 0 %}
+ <div style="clear:both">
+ <p class="search-result-summary">
+ {% if author_name or search_tags or query %}
+ {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} One question found{% plural %}{{q_num}} questions found{% endblocktrans %}
+ {% else %}
+ {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} {{q_num}} question{% plural %}{{q_num}} questions{% endblocktrans %}
+ {% endif %}
+ {% joinitems using ', ' %}
+ {% if author_name %}
+ {% blocktrans %}with {{author_name}}'s contributions{% endblocktrans %}
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ {% trans "tagged" %}
+ "{{ search_tags|join:"\", \"" }}"
+ {% endif %}
+ {% endjoinitems %}
+ </p>
+ {% if author_name or search_tags or query %}
+ <p class="search-tips">{% trans "Search tips:" %}
+ {% ifmany query search_tags author_name %}
+ {% joinitems using ', ' ' or ' %}
+ {% if author_name %}
+ <a href="{% url questions %}?reset_author=true">{% trans "reset author" %}</a>
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ <a href="{% url questions %}?reset_tags=true">{% trans "reset tags" %}</a>
+ {% endif %}
+ {% separator %}
+ {% ifmany query search_tags author_name %}
+ <a href="{% url questions %}?start_over=true">{% trans "start over" %}</a>
+ {% endifmany %}
+ {% endjoinitems %}
+ {% else %}
+ <a href="{% url questions %}?start_over=true">{% trans "start over" %}</a>
+ {% endifmany %}
+ {% trans " - to expand, or dig in by adding more tags and revising the query." %}
+ </p>
+ {% else %}
+ <p class="search-tips">{% trans "Search tip:" %} {% trans "add tags and a query to focus your search" %}</p>
+ {% endif %}
+
+ </div>
+{% endif %}
<div id="listA">
{% include "question_list.html" %}
+ {% comment %}todo: fix css here{% endcomment %}
{% if questions_count == 0 %}
+ {% comment %}todo: add tips to widen selection{% endcomment%}
<p class="evenMore" style="padding-top:30px;text-align:center;">
{% if scope == "unanswered" %}
- {% trans "There are no unanswered questions in this selection" %}
+ {% trans "There are no unanswered questions here" %}
{% endif %}
{% if scope == "favorite" %}
{% trans "No favorite questions here. " %}
- {% trans "Please bookmark some questions with a star and find them here later." %}
+ {% trans "Please start (bookmark) some questions when you visit them" %}
{% endif %}
- {% if scope == "all" %}
- {% trans "Did not find anything? Please feel free to ask your question!" %}
+ </p>
+ {% if query or search_tags or author_name %}
+ <p class="evenMore" style="text-align:center">
+ {% trans "You can expand your search by " %}
+ {% ifmany query search_tags author_name %}
+ {% joinitems using ', ' ' or ' %}
+ {% if author_name %}
+ <a href="{% url questions %}?reset_author=true">{% trans "resetting author" %}</a>
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ <a href="{% url questions %}?reset_tags=true">{% trans "resetting tags" %}</a>
+ {% endif %}
+ {% separator %}
+ {% ifmany query search_tags author_name %}
+ <a href="{% url questions %}?start_over=true">{% trans "starting over" %}</a>
+ {% endifmany %}
+ {% endjoinitems %}
+ {% else %}
+ <a href="{% url questions %}?start_over=true">{% trans "starting over" %}</a>
+ {% endifmany %}
+ </p>
{% endif %}
+ <p class="evenMore" style="text-align:center">
+ <a href="{% url ask %}">{% trans "Please always feel free to ask your question!" %}</a>
</p>
{% else %}
<p class="evenMore" style="padding-left:9px">
@@ -158,51 +228,14 @@ </div>
{% endblock %}
-{% block tail %}
- <div class="pager">{% cnprog_paginator context %}</div>
- <div class="pagesize">{% cnprog_pagesize context %}</div>
-{% endblock %}
+ {% block tail %}
+ {% if questions_count > 10 %}{%comment%}todo: remove magic number{%endcomment%}
+ <div class="pager">{% cnprog_paginator context %}</div>
+ <div class="pagesize">{% cnprog_pagesize context %}</div>
+ {% endif %}
+ {% endblock %}
{% block sidebar %}
-<div class="boxC">
- {% if searchtag %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num and searchtag as tagname %}have total {{q_num}} questions tagged {{tagname}}{% plural %}have total {{q_num}} questions tagged {{tagname}}{% endblocktrans %}
- {% else %}
- {% if searchtitle %}
- {% if settings.USE_SPHINX_SEARCH %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions containing {{searchtitle}} in full text {% plural %} have total {{q_num}} questions containing {{searchtitle}} in full text {% endblocktrans %}
- {% else %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions containing {{searchtitle}} {% plural %} have total {{q_num}} questions containing {{searchtitle}} {% endblocktrans %}
- {% endif %}
- {% else %}
- {% if is_unanswered %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} unanswered questions {% plural %} have total {{q_num}} unanswered questions {% endblocktrans %}
- {% else %}
- {% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %} have total {{q_num}} questions {% plural %} have total {{q_num}} questions {% endblocktrans %}
- {% endif %}
- {% endif %}
- {% endif %}
- <p class="nomargin">
- {% ifequal tab_id "latest" %}
- {% trans "latest questions info" %}
- {% endifequal %}
-
- {% ifequal tab_id "active" %}
- {% trans "Questions are sorted by the <strong>time of last update</strong>." %}
- {% trans "Most recently answered ones are shown first." %}
- {% endifequal %}
-
- {% ifequal tab_id "hottest" %}
- {% trans "Questions sorted by <strong>number of responses</strong>." %}
- {% trans "Most answered questions are shown first." %}
- {% endifequal %}
-
- {% ifequal tab_id "mostvoted" %}
- {% trans "Questions are sorted by the <strong>number of votes</strong>." %}
- {% trans "Most voted questions are shown first." %}
- {% endifequal %}
- </p>
-</div>
{% if request.user.is_authenticated %}
{% include "tag_selector.html" %}
{% endif %}
@@ -210,7 +243,7 @@ <h3 class="subtitle">{% trans "Related tags" %}</h3>
<div class="tags">
{% for tag in tags %}
- <a rel="tag" title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" href="{% url tag_questions tag.name|urlencode %}">{{ tag.name }}</a>
+ <a rel="tag" title="{% blocktrans with tag.name as tag_name %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" href="{% url questions %}?tags={{tag.name|urlencode}}">{{ tag.name }}</a>
<span class="tag-number">× {{ tag.used_count|intcomma }}</span>
<br />
{% endfor %}
diff --git a/forum/skins/default/templates/tag_selector.html b/forum/skins/default/templates/tag_selector.html index 5e3e2ad8..85b858d2 100644 --- a/forum/skins/default/templates/tag_selector.html +++ b/forum/skins/default/templates/tag_selector.html @@ -1,5 +1,6 @@ {% load i18n %} {% load extra_tags %} +{% comment %}todo - maybe disable navigation from ignored tags here when "hide" is on - with js?{%endcomment%} <div id="tagSelector" class="boxC"> <h3 class="subtitle">{% trans "Interesting tags" %}</h3> <div class="tags interesting marked-tags"> @@ -7,8 +8,8 @@ {% spaceless %} <span class="deletable-tag" id="interesting-tag-{{tag_name}}"> <a rel="tag" - title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" - href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a> + title="{% blocktrans %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag_name|urlencode}}">{{tag_name}}</a> <img class="delete-icon" src="{% media "/media/images/close-small-dark.png" %}" title="{% blocktrans %}remove '{{tag_name}}' from the list of interesting tags{% endblocktrans %}"/> @@ -24,8 +25,8 @@ {% spaceless %} <span class="deletable-tag" id="ignored-tag-{{tag_name}}"> <a rel="tag" - title="{% blocktrans with tag as tagname %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" - href="{% url tag_questions tag_name|urlencode %}">{{tag_name}}</a> + title="{% blocktrans %}see questions tagged '{{ tag_name }}'{% endblocktrans %}" + href="{% url questions %}?tags={{tag_name|urlencode}}">{{tag_name}}</a> <img class="delete-icon" src="{% media "/media/images/close-small-dark.png" %}" title="{% blocktrans %}remove '{{tag_name}}' from the list of ignored tags{% endblocktrans %}"/> diff --git a/forum/skins/default/templates/tags.html b/forum/skins/default/templates/tags.html index 50f90fb1..2bc01070 100644 --- a/forum/skins/default/templates/tags.html +++ b/forum/skins/default/templates/tags.html @@ -46,7 +46,8 @@ <ul class="tagsList tags"> {% for tag in tags.object_list %} <li> - <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %}'{{ tag }}'{% trans "using tags" %}" rel="tag"> + <a href="{% url questions %}?tags={{tag|urlencode}}" + title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag"> {{ tag }} </a> <span class="tag-number">× {{ tag.used_count|intcomma }}</span> diff --git a/forum/skins/default/templates/user_stats.html b/forum/skins/default/templates/user_stats.html index 1f462581..482b1228 100644 --- a/forum/skins/default/templates/user_stats.html +++ b/forum/skins/default/templates/user_stats.html @@ -98,7 +98,7 @@ {% for tag in user_tags%} <a rel="tag" title="{% blocktrans with tag.name as tag_name %}see other questions with {{view_user}}'s contributions tagged '{{ tag_name }}' {% endblocktrans %}" - href="{% url tag_questions tag|urlencode %}?user={{view_user.username}}">{{tag.name}}</a> + href="{% url questions %}?tags={{tag|urlencode}}&author={{view_user.id}}&start_over=true">{{tag.name}}</a> <span class="tag-number">× {{ tag.user_tag_usage_count|intcomma }}</span><br/> {% if forloop.counter|divisibleby:"10" %} </td> diff --git a/forum/skins/default/templates/users_questions.html b/forum/skins/default/templates/users_questions.html index be6aaf7d..99a7f90c 100644 --- a/forum/skins/default/templates/users_questions.html +++ b/forum/skins/default/templates/users_questions.html @@ -31,7 +31,7 @@ {% convert2tagname_list question %} {% for tag in question.tagnames %} <!--todo - move trans below to blocktrans --> - <a href="{% url tag_questions tag|urlencode %}" title="{% trans "see questions tagged" %} '{{ tag }}' {% trans "using tags" %}" rel="tag">{{ tag }}</a> + <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{% endblocktrans %}" rel="tag">{{ tag }}</a> {% endfor %} </div> <div class="started"> diff --git a/forum/templatetags/extra_tags.py b/forum/templatetags/extra_tags.py index 382d19f0..a10c473b 100755 --- a/forum/templatetags/extra_tags.py +++ b/forum/templatetags/extra_tags.py @@ -304,8 +304,12 @@ class ItemSeparatorNode(template.Node): return self.content class JoinItemListNode(template.Node): - def __init__(self,separator=ItemSeparatorNode("''"), items=()): + def __init__(self,separator=ItemSeparatorNode("''"), last_separator=None, items=()): self.separator = separator + if last_separator: + self.last_separator = last_separator + else: + self.last_separator = separator self.items = items def render(self,context): out = [] @@ -314,16 +318,34 @@ class JoinItemListNode(template.Node): bit = item.render(context) if not empty_re.search(bit): out.append(bit) - return self.separator.render(context).join(out) + if len(out) == 1: + return out[0] + if len(out) > 1: + last = out.pop() + all_but_last = self.separator.render(context).join(out) + return self.last_separator.render(context).join((all_but_last,last)) + else: + assert(len(out)==0) + return '' @register.tag(name="joinitems") def joinitems(parser,token): try: - tagname,junk,sep_token = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") + tagname, junk, sep_token = token.split_contents() + last_sep_token = None + except: + try: + tagname, junk, sep_token, last_sep_token = token.split_contents() + except: + raise template.TemplateSyntaxError('incorrect usage of joinitems tag first param ' + 'must be \'using\' second - separator and ' + 'optional third - last item separator') if junk == 'using': sep_node = ItemSeparatorNode(sep_token) + if last_sep_token: + last_sep_node = ItemSeparatorNode(last_sep_token) + else: + last_sep_node = None else: raise template.TemplateSyntaxError("joinitems tag requires 'using \"separator html\"' parameters") nodelist = [] @@ -333,7 +355,7 @@ def joinitems(parser,token): if next.contents == 'endjoinitems': break - return JoinItemListNode(separator=sep_node,items=nodelist) + return JoinItemListNode(separator=sep_node,last_separator=last_sep_node,items=nodelist) class BlockMediaUrlNode(template.Node): def __init__(self,nodelist): @@ -436,3 +458,50 @@ def question_counter_widget(question): #returns a dictionary with keys like 'votes_bg', etc return locals() +class IsManyNode(template.Node): + def __init__(self, test_items, true_nodelist, false_nodelist): + self.true_nodelist = true_nodelist + self.false_nodelist = false_nodelist + self.test_items = test_items + def render(self, context): + maybe = False + for item in self.test_items: + is_good = item.resolve(context) + print item, is_good + if maybe == True and is_good: + print 'have many!' + return self.true_nodelist.render(context) + if is_good: + maybe = True + print 'have one item' + return self.false_nodelist.render(context) + +@register.tag(name='ifmany') +def ifmany(parser,token): + """usage {% ifmany item1 item2 item3 ... itemN %} stuff {% endifmany %} + returns content included into the tag if more than one + item evaluates to Tru'ish value - that's the idea + {% else %} is not supported yet + """ + + bits = list(token.split_contents()) + start_tag = bits.pop(0) + + test_items = [] + for bit in bits: + item = parser.compile_filter(bit) + test_items.append(item) + + end_tag = 'end' + start_tag + else_tag = 'else' + true_nodelist = parser.parse((end_tag,else_tag,)) + token = parser.next_token() + if token.contents == else_tag: + print 'have else clause' + false_nodelist = parser.parse((end_tag,)) + token = parser.next_token() + else: + false_nodelist = template.NodeList() + + + return IsManyNode(test_items, true_nodelist, false_nodelist) diff --git a/forum/utils/decorators.py b/forum/utils/decorators.py index e4e7acb3..440e8312 100755 --- a/forum/utils/decorators.py +++ b/forum/utils/decorators.py @@ -22,4 +22,3 @@ def ajax_method(view_func): json = simplejson.dumps(retval) return HttpResponse(json,mimetype='application/json') return wrap - diff --git a/forum/views/readers.py b/forum/views/readers.py index 9e9662dd..01dfc035 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -90,18 +90,15 @@ def questions(request):#a view generating listing of questions, used by 'unanswe if request.user.is_authenticated(): search_state.set_logged_in() - print 'before: ', search_state - form = AdvancedSearchForm(request.GET) if form.is_valid(): - print 'form is valid' - search_state.update_from_user_input(form.cleaned_data) + search_state.update_from_user_input(form.cleaned_data, request.GET) request.session['search_state'] = search_state request.session.modified = True - print 'after: ', search_state - - print 'going into the search' + #force reset for debugging + #search_state.reset() + #request.session.modified = True #have this call implemented for sphinx, mysql and pgsql (qs, meta_data) = Question.objects.run_advanced_search( @@ -113,10 +110,6 @@ def questions(request):#a view generating listing of questions, used by 'unanswe sort_method = search_state.sort ) - print 'got out of the search' - - logging.debug('search state is %s' % search_state) - objects_list = Paginator(qs, search_state.page_size) questions = objects_list.page(search_state.page) @@ -128,17 +121,16 @@ def questions(request):#a view generating listing of questions, used by 'unanswe #todo!!!! #contributors = #User.objects.get_related_to_questions - print 'rendering template!!!' - print 'have %d' % objects_list.count - + #todo: organize variables by type return render_to_response('questions.html', { 'questions' : questions, 'author_name' : meta_data.get('author_name',None), 'tab_id' : search_state.sort, 'questions_count' : objects_list.count, 'tags' : related_tags, + 'query': search_state.query, + 'search_tags' : search_state.tags, 'tags_autocomplete' : tags_autocomplete, - 'searchtag' : search_state.tags, 'is_unanswered' : False,#remove this from template 'interesting_tag_names': meta_data.get('interesting_tag_names',None), 'ignored_tag_names': meta_data.get('ignored_tag_names',None), @@ -163,15 +155,16 @@ def search(request): #generates listing of questions matching a search query - i are useless under the search bar """ if request.method == "GET": - search_type == request.GET.get('t') + search_type = request.GET.get('t') + query = request.GET.get('query') try: page = int(request.GET.get('page', '1')) except ValueError: page = 1 if search_type == 'tag': - return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (keywords.strip(), page)) - elif search_type == "user": - return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (keywords.strip(), page)) + return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (query.strip(), page)) + elif search_type == 'user': + return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (query.strip(), page)) else: raise Http404 else: @@ -205,6 +198,7 @@ def tags(request):#view showing a listing of available tags - plain list tags = objects_list.page(objects_list.num_pages) return render_to_response('tags.html', { + "active_tab": "tags", "tags" : tags, "stag" : stag, "tab_id" : sortby, diff --git a/forum/views/users.py b/forum/views/users.py index 245a1f85..2356bf38 100755 --- a/forum/views/users.py +++ b/forum/views/users.py @@ -63,11 +63,12 @@ def users(request): users = objects_list.page(objects_list.num_pages) return render_to_response('users.html', { - "users" : users, - "suser" : suser, - "keywords" : suser, - "tab_id" : sortby, - "context" : { + 'active_tab': 'users', + 'users' : users, + 'suser' : suser, + 'keywords' : suser, + 'tab_id' : sortby, + 'context' : { 'is_paginated' : is_paginated, 'pages': objects_list.num_pages, 'page': page, diff --git a/forum/views/writers.py b/forum/views/writers.py index b9b1aad5..57c8e043 100755 --- a/forum/views/writers.py +++ b/forum/views/writers.py @@ -132,9 +132,18 @@ def ask(request):#view used to ask a new question return HttpResponseRedirect(reverse('user_signin_new_question')) else: form = AskForm() + if 'title' in request.GET: + raw_title = request.GET['title'] + form.initial['title'] = strip_tags(strip_entities(raw_title)) + else: + search_state = request.session.get('search_state',None) + if search_state: + query = search_state.query + form.initial['title'] = query tags = _get_tags_cache_json() return render_to_response('ask.html', { + 'active_tab': 'ask', 'form' : form, 'tags' : tags, 'email_validation_faq_url':reverse('faq') + '#validate', @@ -318,7 +327,6 @@ def __generate_comments_json(obj, type, user):#non-view generates json data for data = simplejson.dumps(json_comments) return HttpResponse(data, mimetype="application/json") - def question_comments(request, id):#ajax handler for loading comments to question question = get_object_or_404(Question, id=id) user = request.user diff --git a/settings.py b/settings.py index 4d799a13..b80eb4f2 100644 --- a/settings.py +++ b/settings.py @@ -75,6 +75,7 @@ INSTALLED_APPS = ( 'django_authopenid', 'debug_toolbar' , #'stackexchange', #se loader + 'south', ) AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend',) |