diff options
-rw-r--r-- | askbot/forms.py | 54 | ||||
-rw-r--r-- | askbot/skins/common/templates/authopenid/signup_with_password.html | 2 | ||||
-rw-r--r-- | askbot/skins/default/media/style/style.css | 22 | ||||
-rw-r--r-- | askbot/skins/default/media/style/style.less | 4 | ||||
-rw-r--r-- | askbot/skins/default/templates/feedback.html | 24 | ||||
-rw-r--r-- | askbot/skins/default/templates/macros.html | 2 | ||||
-rw-r--r-- | askbot/skins/default/templates/user_profile/user_stats.html | 2 | ||||
-rw-r--r-- | askbot/views/meta.py | 18 | ||||
-rw-r--r-- | askbot/views/users.py | 58 |
9 files changed, 135 insertions, 51 deletions
diff --git a/askbot/forms.py b/askbot/forms.py index 0769f180..b36f0753 100644 --- a/askbot/forms.py +++ b/askbot/forms.py @@ -43,7 +43,7 @@ def clean_marked_tagnames(tagnames): wildcards.append(tagname) else: pure_tags.append(tagname) - + return pure_tags, wildcards def filter_choices(remove_choices = None, from_choices = None): @@ -75,7 +75,7 @@ COUNTRY_CHOICES = (('unknown',_('select country')),) + countries.COUNTRIES class CountryField(forms.ChoiceField): """this is better placed into the django_coutries app""" - + def __init__(self, *args, **kwargs): """sets label and the country choices """ @@ -253,7 +253,7 @@ class SummaryField(forms.CharField): class DumpUploadForm(forms.Form): """This form handles importing - data into the forum. At the moment it only + data into the forum. At the moment it only supports stackexchange import. """ dump_file = forms.FileField() @@ -397,7 +397,7 @@ class ChangeUserStatusForm(forms.Form): self.fields['user_status'].choices = user_status_choices #set prompt option as default - self.fields['user_status'].default = 'select' + self.fields['user_status'].default = 'select' self.moderator = moderator self.subject = subject @@ -539,11 +539,33 @@ class NotARobotForm(forms.Form): ) class FeedbackForm(forms.Form): - name = forms.CharField(label=_('Your name:'), required=False) - email = forms.EmailField(label=_('Email (not shared with anyone):'), required=False) + name = forms.CharField(label=_('Your name (optional):'), required=False) + email = forms.EmailField(label=_('Email:'), required=False) message = forms.CharField(label=_('Your message:'), max_length=800,widget=forms.Textarea(attrs={'cols':60})) + no_email = forms.BooleanField(label=_("I don't want to give my email:"), required=False) next = NextUrlField() + def __init__(self, is_auth=False, *args, **kwargs): + super(FeedbackForm, self).__init__(*args, **kwargs) + self.is_auth = is_auth + if not is_auth: + if askbot_settings.USE_RECAPTCHA: + self._add_recaptcha_field() + + def _add_recaptcha_field(self): + self.fields['recaptcha'] = RecaptchaField( + private_key = askbot_settings.RECAPTCHA_SECRET, + public_key = askbot_settings.RECAPTCHA_KEY + ) + def clean(self): + super(FeedbackForm, self).clean() + if not self.is_auth: + if not self.cleaned_data['no_email'] and not self.cleaned_data['email']: + msg = _('Please mark "I dont want to give my mail" field.') + self._errors['email'] = self.error_class([msg]) + + return self.cleaned_data + class FormWithHideableFields(object): """allows to swap a field widget to HiddenInput() and back""" @@ -567,7 +589,7 @@ class FormWithHideableFields(object): class AskForm(forms.Form, FormWithHideableFields): """the form used to askbot questions - field ask_anonymously is shown to the user if the + field ask_anonymously is shown to the user if the if ALLOW_ASK_ANONYMOUSLY live setting is True however, for simplicity, the value will always be present in the cleaned data, and will evaluate to False if the @@ -600,7 +622,7 @@ class AskForm(forms.Form, FormWithHideableFields): """ if askbot_settings.ALLOW_ASK_ANONYMOUSLY == False: self.cleaned_data['ask_anonymously'] = False - return self.cleaned_data['ask_anonymously'] + return self.cleaned_data['ask_anonymously'] class AskByEmailForm(forms.Form): @@ -860,16 +882,16 @@ class EditUserForm(forms.Form): ) realname = forms.CharField( - label=_('Real name'), - required=False, - max_length=255, + label=_('Real name'), + required=False, + max_length=255, widget=forms.TextInput(attrs={'size' : 35}) ) website = forms.URLField( - label=_('Website'), - required=False, - max_length=255, + label=_('Website'), + required=False, + max_length=255, widget=forms.TextInput(attrs={'size' : 35}) ) @@ -957,7 +979,7 @@ class TagFilterSelectionForm(forms.ModelForm): if before != after: return True return False - + class EmailFeedSettingField(forms.ChoiceField): def __init__(self, *arg, **kwarg): @@ -1086,7 +1108,7 @@ class SimpleEmailSubscribeForm(forms.Form): ('n',_('no community email please, thanks')) ) subscribe = forms.ChoiceField( - widget=forms.widgets.RadioSelect, + widget=forms.widgets.RadioSelect, error_messages={'required':_('please choose one of the options above')}, choices=SIMPLE_SUBSCRIBE_CHOICES ) diff --git a/askbot/skins/common/templates/authopenid/signup_with_password.html b/askbot/skins/common/templates/authopenid/signup_with_password.html index 43571c20..9911facf 100644 --- a/askbot/skins/common/templates/authopenid/signup_with_password.html +++ b/askbot/skins/common/templates/authopenid/signup_with_password.html @@ -7,7 +7,7 @@ {% endblock %} {% block content %} {% if settings.PASSWORD_REGISTER_SHOW_PROVIDER_BUTTONS == True %} - <h1>{% trans %}Please register by clicking on any of the icons below{% endtrans %}</h1> + <h1 class="section-title">{% trans %}Please register by clicking on any of the icons below{% endtrans %}</h1> <form id="signin-form" method="post" action="{{ settings.LOGIN_URL }}">{% csrf_token %} {# hide_local_login == True because it is password reg form #} {{ diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css index ba5875ad..a1ac17d8 100644 --- a/askbot/skins/default/media/style/style.css +++ b/askbot/skins/default/media/style/style.css @@ -142,6 +142,10 @@ h1 { font-size: 24px; padding: 10px 0 5px 0px; } +/* ----- Extra space above for messages ----- */ +body.user-messages { + margin-top: 2.4em; +} /* ----- Custom positions ----- */ .left { float: left; @@ -453,6 +457,8 @@ h1 { width: 200px; /* widgets for question template */ + /* notify by email box */ + } .box p { margin-bottom: 4px; @@ -596,6 +602,9 @@ h1 { color: #777; text-align: center; } +.box .notify-sidebar #question-subscribe-sidebar { + margin: 7px 0 0 3px; +} .statsWidget p { color: #707070; font-size: 16px; @@ -1875,7 +1884,16 @@ span.delete-icon:hover { .users-page #id_email, .openid-signin #id_name, .meta #id_name, -.users-page #id_name { +.users-page #id_name, +.openid-signin #id_username, +.meta #id_username, +.users-page #id_username, +.openid-signin #id_password1, +.meta #id_password1, +.users-page #id_password1, +.openid-signin #id_password2, +.meta #id_password2, +.users-page #id_password2 { border: #cce6ec 3px solid; height: 25px; padding-left: 5px; @@ -1894,7 +1912,7 @@ span.delete-icon:hover { border: 0; color: #4a757f; font-weight: bold; - font-size: 12px; + font-size: 16px; height: 24px; margin-top: -2px; cursor: pointer; diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less index 543b6157..71e2fc36 100644 --- a/askbot/skins/default/media/style/style.less +++ b/askbot/skins/default/media/style/style.less @@ -2055,7 +2055,7 @@ span.delete-icon:hover { padding-left:0px; font-size:16px; } - #id_email,#id_name{ + #id_email,#id_name,#id_username,#id_password1,#id_password2{ border:#cce6ec 3px solid; height:25px; padding-left:5px; @@ -2074,7 +2074,7 @@ span.delete-icon:hover { border:0; color:@button-label; font-weight:bold; - font-size:12px; + font-size:16px; height:24px; margin-top:-2px; cursor:pointer; diff --git a/askbot/skins/default/templates/feedback.html b/askbot/skins/default/templates/feedback.html index 60ea2fca..85b5d00a 100644 --- a/askbot/skins/default/templates/feedback.html +++ b/askbot/skins/default/templates/feedback.html @@ -3,6 +3,11 @@ {% block title %}{% spaceless %}{% trans %}Feedback{% endtrans %}{% endspaceless %}{% endblock %} {% block content %} <h1 class="section-title">{% trans %}Give us your feedback!{% endtrans %}</h1> +{% if form.errors %} +<span class="error"> + {{form.errors.__all__}} +</span> +{%endif%} <form method="post" action="{% url feedback %}" accept-charset="utf-8">{% csrf_token %} {% if user.is_authenticated() %} <p class="message"> @@ -22,10 +27,18 @@ <div class="form-row"> <label>{{form.email.label}} {% if form.errors.email %} - <span class='error'>{% trans %}(please enter a valid email){% endtrans %}</span> + <span class='error'>{% trans %}(to hear from us please enter a valid email or check the box below){% endtrans %}</span> {% endif %} </label><br/>{{form.email}} </div> + <div class="form-row"> + <label>{{form.no_email.label}} + {% if form.errors.no_email %} + <span class="error">{% trans %}(this field is required){% endtrans %}</span> + {% endif %} + {{form.no_email}} + </label> + </div> {% endif %} <div class="form-row"> <label>{{form.message.label}} @@ -36,6 +49,15 @@ <br/> {{form.message}} </div> + {% if form.recaptcha %} + <div class="form-row"> + {% if form.errors.recaptcha%} + <span class="error">{% trans %}(Please solve the captcha){% endtrans %}</span> + </label> + {% endif %} + {{form.recaptcha}} + </div> + {% endif %} {{form.next}} <div class="submit-row"> <input type="submit" class="submit" value="{% trans %}Send Feedback{% endtrans %}"/> diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html index 680b9d7b..22272e9f 100644 --- a/askbot/skins/default/templates/macros.html +++ b/askbot/skins/default/templates/macros.html @@ -221,7 +221,7 @@ poor design of the data or methods on data objects #} title="{% trans %}see questions tagged '{{ tag }}'{% endtrans %}" {% endif %} rel="tag" - >{{ tag|replace('*', '✽') }}</{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %}> + >{{ tag|replace('*', '✽')|truncate(20,True)}}</{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %}> {% if deletable %} <span class="delete-icon" {% if delete_link_title %} diff --git a/askbot/skins/default/templates/user_profile/user_stats.html b/askbot/skins/default/templates/user_profile/user_stats.html index d9002d30..2551015c 100644 --- a/askbot/skins/default/templates/user_profile/user_stats.html +++ b/askbot/skins/default/templates/user_profile/user_stats.html @@ -8,7 +8,7 @@ {% include "user_profile/user_info.html" %} <a name="questions"></a> {% spaceless %} - <h2>{% trans counter=questions|length %}<span class="count">{{counter}}</span> Question{% pluralize %}<span class="count">{{counter}}</span> Questions{% endtrans %}</h2> + <h2>{% trans counter=question_count %}<span class="count">{{counter}}</span> Question{% pluralize %}<span class="count">{{counter}}</span> Questions{% endtrans %}</h2> {% endspaceless %} {% include "user_profile/users_questions.html" %} <a name="answers"></a> diff --git a/askbot/views/meta.py b/askbot/views/meta.py index 301a0925..493ab8ec 100644 --- a/askbot/views/meta.py +++ b/askbot/views/meta.py @@ -33,13 +33,13 @@ def config_variable(request, variable_name = None, mimetype = None): return HttpResponse(output, mimetype = mimetype) def about(request, template='about.html'): - return generic_view(request, template = template, page_class = 'meta') + return generic_view(request, template = template, page_class = 'meta') def page_not_found(request, template='404.html'): - return generic_view(request, template) + return generic_view(request, template) def server_error(request, template='500.html'): - return generic_view(request, template) + return generic_view(request, template) def faq(request): if getattr(askbot_settings, 'FORUM_FAQ',''): @@ -64,7 +64,7 @@ def faq(request): #'send_email_key_url': reverse('send_email_key'), 'ask_question_url': reverse('ask'), 'page_class': 'meta', - } + } return render_into_skin('faq_static.html', data, request) @csrf.csrf_protect @@ -72,9 +72,10 @@ def feedback(request): data = {'page_class': 'meta'} form = None if request.method == "POST": - form = FeedbackForm(request.POST) + form = FeedbackForm(is_auth = request.user.is_authenticated(), + data = request.POST) if form.is_valid(): - if not request.user.is_authenticated: + if not request.user.is_authenticated(): data['email'] = form.cleaned_data.get('email',None) data['message'] = form.cleaned_data['message'] data['name'] = form.cleaned_data.get('name',None) @@ -85,7 +86,8 @@ def feedback(request): request.user.message_set.create(message=msg) return HttpResponseRedirect(get_next_url(request)) else: - form = FeedbackForm(initial={'next':get_next_url(request)}) + form = FeedbackForm(is_auth = request.user.is_authenticated(), + initial={'next':get_next_url(request)}) data['form'] = form return render_into_skin('feedback.html', data, request) @@ -96,7 +98,7 @@ def privacy(request): def badges(request):#user status/reputation system #todo: supplement database data with the stuff from badges.py - known_badges = badge_data.BADGES.keys() + known_badges = badge_data.BADGES.keys() badges = BadgeData.objects.filter(slug__in = known_badges).order_by('slug') my_badges = [] if request.user.is_authenticated(): diff --git a/askbot/views/users.py b/askbot/views/users.py index 130f79a4..deaccb8c 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -1,7 +1,7 @@ """ :synopsis: user-centric views for askbot -This module includes all views that are specific to a given user - his or her profile, +This module includes all views that are specific to a given user - his or her profile, and other views showing profile-related information. Also this module includes the view listing all forum users. @@ -75,7 +75,7 @@ def owner_or_moderator_required(f): params = '?next=%s' % request.path return HttpResponseRedirect(reverse('user_signin') + params) return f(request, profile_owner, context) - return wrapped_func + return wrapped_func def users(request): is_paginated = True @@ -100,7 +100,7 @@ def users(request): objects_list = Paginator( models.User.objects.all().order_by( order_by_parameter - ), + ), const.USERS_PAGE_SIZE ) base_url = reverse('users') + '?sort=%s&' % sortby @@ -111,7 +111,7 @@ def users(request): username__icontains = suser ).order_by( '-reputation' - ), + ), const.USERS_PAGE_SIZE ) base_url = reverse('users') + '?name=%s&sort=%s&' % (suser, sortby) @@ -145,7 +145,7 @@ def users(request): @csrf.csrf_protect def user_moderate(request, subject, context): - """user subview for moderation + """user subview for moderation """ moderator = request.user @@ -174,7 +174,7 @@ def user_moderate(request, subject, context): if send_message_form.is_valid(): subject_line = send_message_form.cleaned_data['subject_line'] body_text = send_message_form.cleaned_data['body_text'] - + try: send_mail( subject_line = subject_line, @@ -244,7 +244,7 @@ def set_new_email(user, new_email, nomessage=False): user.email_isvalid = False user.save() #if askbot_settings.EMAIL_VALIDATION == True: - # send_new_email_key(user,nomessage=nomessage) + # send_new_email_key(user,nomessage=nomessage) @login_required @csrf.csrf_protect @@ -309,7 +309,26 @@ def user_stats(request, user, context): 'last_activity_by__silver', 'last_activity_by__bronze' )[:100] + questions = list(questions) + + #added this if to avoid another query if questions is less than 100 + if len(questions) < 100: + question_count = len(questions) + else: + question_count = models.Question.objects.filter( + **question_filter + ).order_by( + '-score', '-last_activity_at' + ).select_related( + 'last_activity_by__id', + 'last_activity_by__username', + 'last_activity_by__reputation', + 'last_activity_by__gold', + 'last_activity_by__silver', + 'last_activity_by__bronze' + ).count() + favorited_myself = models.FavoriteQuestion.objects.filter( question__in = questions, user = user @@ -384,6 +403,7 @@ def user_stats(request, user, context): 'page_title' : _('user profile overview'), 'user_status_for_display': user.get_status_display(soft = True), 'questions' : questions, + 'question_count': question_count, 'question_type' : question_type, 'answer_type' : answer_type, 'favorited_myself': favorited_myself, @@ -417,7 +437,7 @@ def user_recent(request, user, context): self.summary = summary slug_title = slugify(title) self.title_link = reverse( - 'question', + 'question', kwargs={'id':question_id} ) + u'%s' % slug_title if int(answer_id) > 0: @@ -459,11 +479,11 @@ def user_recent(request, user, context): for q in questions: q_event = Event( - q['active_at'], - q['activity_type'], - q['title'], - '', - '0', + q['active_at'], + q['activity_type'], + q['title'], + '', + '0', q['question_id'] ) activities.append(q_event) @@ -479,8 +499,8 @@ def user_recent(request, user, context): 'activity_type' : 'activity.activity_type' }, tables=['activity', 'answer', 'question'], - where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' + - 'answer.question_id=question.id AND NOT answer.deleted AND activity.user_id=%s AND '+ + where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' + + 'answer.question_id=question.id AND NOT answer.deleted AND activity.user_id=%s AND '+ 'activity.activity_type=%s AND NOT question.deleted'], params=[answer_type_id, user.id, const.TYPE_ACTIVITY_ANSWER], order_by=['-activity.active_at'] @@ -701,7 +721,7 @@ def user_recent(request, user, context): @owner_or_moderator_required def user_responses(request, user, context): """ - We list answers for question, comments, and + We list answers for question, comments, and answer accepted by others for this user. as well as mentions of the user @@ -762,7 +782,7 @@ def user_responses(request, user, context): #todo: agrupate users if response['response_id'] == last_response_id: original_response = dict.copy(filtered_response_list[len(filtered_response_list)-1]) - original_response['nested_responses'].append(response) + original_response['nested_responses'].append(response) filtered_response_list[len(filtered_response_list)-1] = original_response else: filtered_response_list.append(response) @@ -864,8 +884,8 @@ def user_reputation(request, user, context): reputes = models.Repute.objects.filter(user=user).order_by('-reputed_at') #select_related() adds stuff needed for the query reputes = reputes.select_related( - 'question__title', - 'question__id', + 'question__title', + 'question__id', 'user__username' ) #prepare data for the graph |