summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdolfo Fitoria <adolfo.fitoria@gmail.com>2011-08-29 09:24:34 -0300
committerAdolfo Fitoria <adolfo.fitoria@gmail.com>2011-08-29 09:24:34 -0300
commit17cae403479377417c63a90ca395d25026c0a7ea (patch)
tree3e6f87ebabfc6010005064423ac2b64af0249028
parent716e31ebce9c695775100f3e35244108b1cbc204 (diff)
parent79d1a1d9ba1c275bd5af0ed9bb2794facd137ae5 (diff)
downloadaskbot-17cae403479377417c63a90ca395d25026c0a7ea.tar.gz
askbot-17cae403479377417c63a90ca395d25026c0a7ea.tar.bz2
askbot-17cae403479377417c63a90ca395d25026c0a7ea.zip
Merge branch 'master' into avatars-sidebar
Conflicts: askbot/models/__init__.py
-rw-r--r--askbot/__init__.py2
-rw-r--r--askbot/conf/login_providers.py33
-rw-r--r--askbot/conf/social_sharing.py9
-rw-r--r--askbot/deps/django_authopenid/backends.py12
-rw-r--r--askbot/deps/django_authopenid/forms.py2
-rw-r--r--askbot/deps/django_authopenid/util.py13
-rw-r--r--askbot/deps/django_authopenid/views.py30
-rw-r--r--askbot/deps/livesettings/values.py10
-rw-r--r--askbot/doc/source/changelog.rst46
-rw-r--r--askbot/doc/source/conf.py8
-rw-r--r--askbot/doc/source/index.rst1
-rw-r--r--askbot/doc/source/initialize-database-tables.rst8
-rw-r--r--askbot/doc/source/optional-modules.rst13
-rw-r--r--askbot/importers/stackexchange/management/commands/load_stackexchange.py3
-rw-r--r--askbot/locale/es/LC_MESSAGES/django.po24
-rw-r--r--askbot/models/__init__.py20
-rw-r--r--askbot/models/meta.py2
-rw-r--r--askbot/skins/default/media/images/sprite.pngbin5095 -> 5325 bytes
-rw-r--r--askbot/skins/default/media/jquery-openid/jquery.openid.js4
-rw-r--r--askbot/skins/default/media/js/post.js12
-rw-r--r--askbot/skins/default/media/js/utils.js6
-rw-r--r--askbot/skins/default/media/style/style.css11
-rw-r--r--askbot/skins/default/templates/authopenid/signin.html2
-rw-r--r--askbot/skins/default/templates/macros.html11
-rw-r--r--askbot/skins/default/templates/question.html4
-rw-r--r--askbot/startup_procedures.py14
-rw-r--r--askbot/utils/mail.py36
27 files changed, 288 insertions, 48 deletions
diff --git a/askbot/__init__.py b/askbot/__init__.py
index 4ca440d7..d56557d9 100644
--- a/askbot/__init__.py
+++ b/askbot/__init__.py
@@ -9,7 +9,7 @@ import smtplib
import sys
import logging
-VERSION = (0, 7, 19)
+VERSION = (0, 7, 20)
#necessary for interoperability of django and coffin
try:
diff --git a/askbot/conf/login_providers.py b/askbot/conf/login_providers.py
index 56423ca4..a97baa9d 100644
--- a/askbot/conf/login_providers.py
+++ b/askbot/conf/login_providers.py
@@ -5,6 +5,7 @@ from askbot.conf.settings_wrapper import settings
from askbot.deps import livesettings
from django.utils.translation import ugettext as _
from django.conf import settings as django_settings
+from askbot.skins import utils as skin_utils
LOGIN_PROVIDERS = livesettings.ConfigurationGroup(
'LOGIN_PROVIDERS',
@@ -29,6 +30,38 @@ settings.register(
)
)
+settings.register(
+ livesettings.BooleanValue(
+ LOGIN_PROVIDERS,
+ 'SIGNIN_WORDPRESS_SITE_ENABLED',
+ default = False,
+ description=_('Activate to allow login with self-hosted wordpress site'),
+ help_text=_('to activate this feature you must fill out the wordpress xml-rpc setting bellow')
+ )
+)
+
+settings.register(
+ livesettings.URLValue(
+ LOGIN_PROVIDERS,
+ 'WORDPRESS_SITE_URL',
+ default = '',
+ description=_('Fill it with the wordpress url to the xml-rpc, normally http://mysite.com/xmlrpc.php'),
+ help_text=_('To enable, go to Settings->Writing->Remote Publishing and check the box for XML-RPC')
+ )
+)
+
+settings.register(
+ livesettings.ImageValue(
+ LOGIN_PROVIDERS,
+ 'WORDPRESS_SITE_ICON',
+ upload_directory = django_settings.ASKBOT_FILE_UPLOAD_DIR,
+ upload_url = '/' + django_settings.ASKBOT_UPLOADED_FILES_URL,
+ default = '/images/logo.gif',
+ description = _('Upload your icon'),
+ url_resolver = skin_utils.get_media_url
+ )
+)
+
providers = (
'local',
'AOL',
diff --git a/askbot/conf/social_sharing.py b/askbot/conf/social_sharing.py
index 0ea5f9be..db01fb49 100644
--- a/askbot/conf/social_sharing.py
+++ b/askbot/conf/social_sharing.py
@@ -40,6 +40,15 @@ settings.register(
settings.register(
BooleanValue(
SOCIAL_SHARING,
+ 'ENABLE_SHARING_IDENTICA',
+ default=True,
+ description=_('Check to enable sharing of questions on Identi.ca')
+ )
+)
+
+settings.register(
+ BooleanValue(
+ SOCIAL_SHARING,
'ENABLE_SHARING_GOOGLE',
default=True,
description=_('Check to enable sharing of questions on Google+')
diff --git a/askbot/deps/django_authopenid/backends.py b/askbot/deps/django_authopenid/backends.py
index a9eee8e5..e608086c 100644
--- a/askbot/deps/django_authopenid/backends.py
+++ b/askbot/deps/django_authopenid/backends.py
@@ -30,6 +30,8 @@ class AuthBackend(object):
oauth_user_id = None,#used with oauth
facebook_user_id = None,#user with facebook
ldap_user_id = None,#for ldap
+ wordpress_url = None, # required for self hosted wordpress
+ wp_user_id = None, # required for self hosted wordpress
method = None,#requried parameter
):
"""this authentication function supports many login methods
@@ -149,6 +151,16 @@ class AuthBackend(object):
except UserAssociation.DoesNotExist:
return None
+ elif method == 'wordpress_site':
+ try:
+ custom_wp_openid_url = '%s?user_id=%s' % (wordpress_url, wp_user_id)
+ assoc = UserAssociation.objects.get(
+ openid_url = custom_wp_openid_url,
+ provider_name = 'wordpress_site'
+ )
+ user = assoc.user
+ except UserAssociation.DoesNotExist:
+ return None
elif method == 'force':
return self.get_user(user_id)
else:
diff --git a/askbot/deps/django_authopenid/forms.py b/askbot/deps/django_authopenid/forms.py
index d9bb7261..c4507272 100644
--- a/askbot/deps/django_authopenid/forms.py
+++ b/askbot/deps/django_authopenid/forms.py
@@ -215,6 +215,8 @@ class LoginForm(forms.Form):
elif provider_type == 'facebook':
self.cleaned_data['login_type'] = 'facebook'
#self.do_clean_oauth_fields()
+ elif provider_type == 'wordpress_site':
+ self.cleaned_data['login_type'] = 'wordpress_site'
return self.cleaned_data
diff --git a/askbot/deps/django_authopenid/util.py b/askbot/deps/django_authopenid/util.py
index 0226f56c..4468a6d2 100644
--- a/askbot/deps/django_authopenid/util.py
+++ b/askbot/deps/django_authopenid/util.py
@@ -34,7 +34,7 @@ from models import Association, Nonce
__all__ = ['OpenID', 'DjangoOpenIDStore', 'from_openid_response', 'clean_next']
-ALLOWED_LOGIN_TYPES = ('password', 'oauth', 'openid-direct', 'openid-username')
+ALLOWED_LOGIN_TYPES = ('password', 'oauth', 'openid-direct', 'openid-username', 'wordpress')
class OpenID:
def __init__(self, openid_, issued, attrs=None, sreg_=None):
@@ -163,6 +163,8 @@ def use_password_login():
either if USE_RECAPTCHA is false
of if recaptcha keys are set correctly
"""
+ if askbot_settings.SIGNIN_WORDPRESS_SITE_ENABLED:
+ return True
if askbot_settings.USE_RECAPTCHA:
if askbot_settings.RECAPTCHA_KEY and askbot_settings.RECAPTCHA_SECRET:
return True
@@ -436,7 +438,14 @@ def get_enabled_major_login_providers():
if matches:
return matches.group(1)
raise OAuthError()
-
+
+ if askbot_settings.SIGNIN_WORDPRESS_SITE_ENABLED and askbot_settings.WORDPRESS_SITE_URL:
+ data['wordpress_site'] = {
+ 'name': 'wordpress_site',
+ 'display_name': 'Self hosted wordpress blog', #need to be added as setting.
+ 'icon_media_path': askbot_settings.WORDPRESS_SITE_ICON,
+ 'type': 'wordpress_site',
+ }
if askbot_settings.LINKEDIN_KEY and askbot_settings.LINKEDIN_SECRET:
data['linkedin'] = {
'name': 'linkedin',
diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py
index 5610a7fb..63c3b1f0 100644
--- a/askbot/deps/django_authopenid/views.py
+++ b/askbot/deps/django_authopenid/views.py
@@ -59,6 +59,14 @@ try:
except ImportError:
from yadis import xri
+try:
+ from xmlrpclib import Fault as WpFault
+ from wordpress_xmlrpc import Client
+ from wordpress_xmlrpc.methods.users import GetUserInfo
+except ImportError:
+ pass
+
+
import urllib
from askbot import forms as askbot_forms
from askbot.deps.django_authopenid import util
@@ -438,6 +446,28 @@ def signin(request):
) % {'provider': 'Facebook'}
request.user.message_set.create(message = msg)
+ elif login_form.cleaned_data['login_type'] == 'wordpress_site':
+ #here wordpress_site means for a self hosted wordpress blog not a wordpress.com blog
+ wp = Client(askbot_settings.WORDPRESS_SITE_URL, login_form.cleaned_data['username'], login_form.cleaned_data['password'])
+ try:
+ wp_user = wp.call(GetUserInfo())
+ custom_wp_openid_url = '%s?user_id=%s' % (wp.url, wp_user.user_id)
+ user = authenticate(
+ method = 'wordpress_site',
+ wordpress_url = wp.url,
+ wp_user_id = wp_user.user_id
+ )
+ return finalize_generic_signin(
+ request = request,
+ user = user,
+ user_identifier = custom_wp_openid_url,
+ login_provider_name = provider_name,
+ redirect_url = next_url
+ )
+ except WpFault, e:
+ logging.critical(unicode(e))
+ msg = _('The login password combination was not correct')
+ request.user.message_set.create(message = msg)
else:
#raise 500 error - unknown login type
pass
diff --git a/askbot/deps/livesettings/values.py b/askbot/deps/livesettings/values.py
index 740d9884..6372e656 100644
--- a/askbot/deps/livesettings/values.py
+++ b/askbot/deps/livesettings/values.py
@@ -21,7 +21,7 @@ import os
__all__ = ['BASE_GROUP', 'ConfigurationGroup', 'Value', 'BooleanValue', 'DecimalValue', 'DurationValue',
'FloatValue', 'IntegerValue', 'ModuleValue', 'PercentValue', 'PositiveIntegerValue', 'SortedDotDict',
- 'StringValue', 'ImageValue', 'LongStringValue', 'MultipleStringValue']
+ 'StringValue', 'ImageValue', 'LongStringValue', 'MultipleStringValue', 'URLValue']
_WARN = {}
@@ -545,6 +545,14 @@ class StringValue(Value):
to_editor = to_python
+class URLValue(Value):
+
+ class field(forms.URLField):
+
+ def __init__(self, *args, **kwargs):
+ kwargs['required'] = False
+ forms.URLField.__init__(self, *args, **kwargs)
+
class LongStringValue(Value):
class field(forms.CharField):
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
new file mode 100644
index 00000000..523a011f
--- /dev/null
+++ b/askbot/doc/source/changelog.rst
@@ -0,0 +1,46 @@
+Changes in Askbot
+=================
+
+Development version (not yet on pypi)
+-------------------------------------
+* First user automatically becomes site administrator (Adolfo Fitoria)
+
+0.7.20 (Current Version)
+------------------------
+* Added support for login via self-hosted Wordpress site (Adolfo Fitoria)
+* Allowed basic markdown in the comments (Adolfo Fitoria)
+* Added this changelog (Adolfo Fitoria)
+* Added support for threaded emails (Benoit Lavigne)
+* A few more Spanish translation strings (Byron Corrales)
+* Social sharing support on identi.ca (Rantadeep Debnath)
+
+0.7.19
+------
+* Changed the Favorite question function for Follow question.
+* Fixed issues with page load time.
+* Added notify me checkbox to the sidebar.
+* Removed MySql dependency from setup.py
+* Fixed Facebook login.
+* `Fixed "Moderation tab is misaligned" issue reported by methner. <http://askbot.org/en/question/587/moderation-tab-is-misaligned-fixed>`_
+* Fixed bug in follow users and changed the follow button design.
+
+0.7.18
+------
+* `Added multiple capitalization to username mentions(reported by niles) <http://askbot.org/en/question/580/allow-alternate-capitalizations-in-user-links>`_
+
+0.7.17
+------
+* Adding test for UserNameField.
+* Adding test for markup functions.
+
+0.7.16
+------
+* Admins can add aministrators too.
+* Added a postgres driver version check in the start procedures due to a bug in psycopg2 2.4.2.
+* New inbox system style (`bug reported by Tomasz P. Szynalski <http://askbot.org/en/question/470/answerscomments-are-listed-twice-in-the-inbox>`_).
+
+0.7.15
+------
+* Fixed integration with Django 1.1.
+* Fixed bugs in setup script.
+* Fixed pypi bugs.
diff --git a/askbot/doc/source/conf.py b/askbot/doc/source/conf.py
index 09fe821f..d8848317 100644
--- a/askbot/doc/source/conf.py
+++ b/askbot/doc/source/conf.py
@@ -61,16 +61,16 @@ master_doc = 'index'
# General information about the project.
project = u'Askbot'
-copyright = u'2010, Askbot Project'
+copyright = u'2011, Askbot Project'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
-#
# The short X.Y version.
-version = '0.6'
+from askbot import get_version
+version = get_version()
# The full version, including alpha/beta/rc tags.
-release = '0.6'
+release = get_version()
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/askbot/doc/source/index.rst b/askbot/doc/source/index.rst
index 2653b2df..98dbf777 100644
--- a/askbot/doc/source/index.rst
+++ b/askbot/doc/source/index.rst
@@ -27,6 +27,7 @@ at the forum_ or by email at admin@askbot.org
Appendix E: Customizing skin in askbot <customizing-skin-in-askbot>
Footnotes <footnotes>
Contributors <contributors>
+ Changelog<changelog>
Some background information: Askbot is written in Python on top of the Django platform.
Code of Askbot grew out of CNPROG project originally written by
diff --git a/askbot/doc/source/initialize-database-tables.rst b/askbot/doc/source/initialize-database-tables.rst
index 26993985..f1281816 100644
--- a/askbot/doc/source/initialize-database-tables.rst
+++ b/askbot/doc/source/initialize-database-tables.rst
@@ -38,9 +38,13 @@ Connect to the Django development server with your Web browser. The address is t
Once the fresh copy of Askbot appears in your browser, create a new account at the site.
This will be your administrator account.
-Finally, turn the newly added user into a superuser by running::
+.. deprecated:: 0.7.20.
+ Finally, turn the newly added user into a superuser by running::
- python manage.py add_admin 1
+ python manage.py add_admin 1
+
+.. versionadded:: 0.7.20.
+ In the new version of Askbot the first user you create on the site will be added as administrator.
Here number 1 is the numeric id of the first user, enter a different number, if it is indeed different.
diff --git a/askbot/doc/source/optional-modules.rst b/askbot/doc/source/optional-modules.rst
index 1da5a349..164f2f8c 100644
--- a/askbot/doc/source/optional-modules.rst
+++ b/askbot/doc/source/optional-modules.rst
@@ -123,3 +123,16 @@ Also, settings ``MEDIA_ROOT`` and ``MEDIA_URL`` will need to be added to your ``
Version of the ``avatar`` application available at pypi may not
be up to date, so please take the development version from the
github repository
+
+Wordpress Integration
+=====================
+
+To enable authentication for self hosted wordpress sites(wordpress.com blogs will work with openid login). To enable it follow the following steps:
+
+* Check if you have the package `"python_wordpress_xmlrpc <http://pypi.python.org/pypi/python-wordpress-xmlrpc/1.4>`_ from pypi.
+* Go to your wordpress blog admin panel and serch for: Settings->Writing->Remote Publishing then check the box for XML-RPC.
+* Go back to your askbot site settings and click on *Login Provider Settings* and then activate the option *Activate to allow login with self-hosted wordpress site*,
+* Input your blog url to the xmlrpc.php file it will look something like this http://yoursite.com/xmlrpc.php
+* Upload an icon for display in the login area.
+
+After doing this steps you should be able to login with your self hosted wordpress site user/password combination.
diff --git a/askbot/importers/stackexchange/management/commands/load_stackexchange.py b/askbot/importers/stackexchange/management/commands/load_stackexchange.py
index a226bd61..20155e36 100644
--- a/askbot/importers/stackexchange/management/commands/load_stackexchange.py
+++ b/askbot/importers/stackexchange/management/commands/load_stackexchange.py
@@ -3,6 +3,7 @@ DEBUGME = False
import os
import re
import sys
+from unidecode import unidecode
import zipfile
from datetime import datetime
from django.core.management.base import BaseCommand, CommandError
@@ -735,7 +736,7 @@ class Command(BaseCommand):
def _report_missing_badges(self):
d = self._missing_badges
unused = [name for name in d.keys() if d[name] == 0]
- dropped = [name for name in d.keys() if d[name] > 0]
+ dropped = [unidecode(name) for name in d.keys() if d[name] > 0]
print 'Warning - following unsupported badges were dropped:'
print ', '.join(dropped)
sys.stdout.flush()
diff --git a/askbot/locale/es/LC_MESSAGES/django.po b/askbot/locale/es/LC_MESSAGES/django.po
index 1b8d68f3..869b3d58 100644
--- a/askbot/locale/es/LC_MESSAGES/django.po
+++ b/askbot/locale/es/LC_MESSAGES/django.po
@@ -159,7 +159,7 @@ msgstr ""
#: forms.py:261
msgid "Cannot change status of another moderator"
-msgstr ""
+msgstr "No esta permitido cambiar el estado de otro moderador"
#: forms.py:267
#, python-format
@@ -172,7 +172,7 @@ msgstr ""
#: forms.py:283
msgid "Message text"
-msgstr ""
+msgstr "Mensaje de Texto"
#: forms.py:360
msgid "Your name:"
@@ -457,11 +457,11 @@ msgstr ""
#: conf/external_keys.py:58
msgid "Recaptcha public key"
-msgstr ""
+msgstr "Llave pública de Recaptcha"
#: conf/external_keys.py:66
msgid "Recaptcha private key"
-msgstr ""
+msgstr "Llave privada de Recaptcha"
#: conf/external_keys.py:68
msgid ""
@@ -472,7 +472,7 @@ msgstr ""
#: conf/external_keys.py:80
msgid "Facebook public API key"
-msgstr ""
+msgstr "Llave pública para API de Facebook"
#: conf/external_keys.py:82
msgid ""
@@ -558,16 +558,16 @@ msgstr ""
#: conf/forum_data_rules.py:29
msgid "Maximum length of tag (number of characters)"
-msgstr ""
+msgstr "Tamaño máximo de una etiqueta (número de caracteres)"
#: conf/forum_data_rules.py:39
msgid "Default max number of comments to display under posts"
-msgstr ""
+msgstr "Cantidad máxima por defecto, de comentarios a mostrarse para cada entrada"
#: conf/forum_data_rules.py:50
#, python-format
msgid "Maximum comment length, must be < %(max_len)s"
-msgstr ""
+msgstr "Tamaño máximo de un comentario, debe ser menor a %(max_len)s"
#: conf/forum_data_rules.py:60
msgid "Minimum length of search term for Ajax search"
@@ -579,11 +579,11 @@ msgstr ""
#: conf/forum_data_rules.py:70
msgid "Maximum number of tags per question"
-msgstr ""
+msgstr "Número máximo de etiquetas por cada pregunta"
#: conf/forum_data_rules.py:82
msgid "Number of questions to list by default"
-msgstr ""
+msgstr "Número máximo de preguntas a listar por defecto"
#: conf/forum_data_rules.py:92
#, fuzzy
@@ -654,7 +654,7 @@ msgstr "comentar"
#: conf/minimum_reputation.py:56
msgid "Delete comments posted by others"
-msgstr ""
+msgstr "Borrar comentarios creados por otros usuarios"
#: conf/minimum_reputation.py:65
#, fuzzy
@@ -674,7 +674,7 @@ msgstr "Cerrar pregunta"
#: conf/minimum_reputation.py:92
msgid "Retag questions posted by other people"
-msgstr ""
+msgstr "Re-etiquetar las preguntas creadas por otros usuarios"
#: conf/minimum_reputation.py:101
#, fuzzy
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index d87b5ce9..5407b1e2 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -1310,14 +1310,11 @@ def user_post_answer(
minutes = int(diff.seconds/60)
if days > 2:
- if date.year == now.year:
- date_token = date.strftime("%b %d")
+ if asked.year == now.year:
+ date_token = asked.strftime("%b %d")
else:
- date_token = date.strftime("%b %d '%y")
- if use_on_prefix:
- left = _('on %(date)s') % { 'date': date_token }
- else:
- left = date_token
+ date_token = asked.strftime("%b %d '%y")
+ left = _('on %(date)s') % { 'date': date_token }
elif days == 2:
left = _('in two days')
elif days == 1:
@@ -2271,7 +2268,8 @@ def send_instant_notifications_about_activity_in_post(
body_text = body_text,
recipient_list = [user.email],
related_object = origin_post,
- activity_type = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT
+ activity_type = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT,
+ headers = mail.thread_headers(post, origin_post, update_activity.activity_type)
)
@@ -2572,7 +2570,13 @@ def update_user_has_custom_avatar_flag(instance, **kwargs):
def set_user_has_valid_gravatar_flag(instance, **kwargs):
instance.update_has_valid_gravatar()
+def make_admin_if_first_user(instance, **kwargs):
+ user_count = User.objects.all().count()
+ if user_count == 0:
+ instance.set_admin_status()
+
#signal for User model save changes
+django_signals.pre_save.connect(make_admin_if_first_user, sender=User)
django_signals.pre_save.connect(calculate_gravatar_hash, sender=User)
django_signals.post_save.connect(add_missing_subscriptions, sender=User)
#django_signals.post_save.connect(set_user_has_valid_gravatar_flag, sender=User)
diff --git a/askbot/models/meta.py b/askbot/models/meta.py
index 7cccbcd6..463db0cc 100644
--- a/askbot/models/meta.py
+++ b/askbot/models/meta.py
@@ -91,7 +91,7 @@ class Comment(base.MetaContent, base.UserContent):
offensive_flag_count = models.IntegerField(default = 0)
_urlize = True
- _use_markdown = False
+ _use_markdown = True
_escape_html = True
is_anonymous = False #comments are never anonymous - may change
diff --git a/askbot/skins/default/media/images/sprite.png b/askbot/skins/default/media/images/sprite.png
index fadc0f28..1a0fbc78 100644
--- a/askbot/skins/default/media/images/sprite.png
+++ b/askbot/skins/default/media/images/sprite.png
Binary files differ
diff --git a/askbot/skins/default/media/jquery-openid/jquery.openid.js b/askbot/skins/default/media/jquery-openid/jquery.openid.js
index c8349e8e..bb76fcd6 100644
--- a/askbot/skins/default/media/jquery-openid/jquery.openid.js
+++ b/askbot/skins/default/media/jquery-openid/jquery.openid.js
@@ -410,6 +410,10 @@ $.fn.authenticator = function() {
signin_page.find('input.password'),
start_password_login_or_change
);
+ setup_event_handlers(
+ signin_page.find('input.wordpress_site'),
+ start_password_login_or_change
+ );
setup_event_handlers(account_recovery_link, start_account_recovery);
diff --git a/askbot/skins/default/media/js/post.js b/askbot/skins/default/media/js/post.js
index 70cbe824..8216c10a 100644
--- a/askbot/skins/default/media/js/post.js
+++ b/askbot/skins/default/media/js/post.js
@@ -1040,6 +1040,12 @@ EditCommentForm.prototype.createDom = function(){
this._textarea = $('<textarea></textarea>');
this._textarea.attr('id', this._id);
+ this._help_text = $('<span></span>').attr('class', 'help-text');
+ this._help_text.html(gettext('Markdown is allowed in the comments'));
+ div.append(this._help_text);
+
+ this._help_text = $('<div></div>').attr('class', 'clearfix');
+ div.append(this._help_text);
this._element.append(div);
div.append(this._textarea);
@@ -1524,6 +1530,10 @@ var socialSharing = function(){
var SERVICE_DATA = {
//url - template for the sharing service url, params are for the popup
+ identica: {
+ url: "http://identi.ca/index.php?action=newnotice&status_textarea={TEXT}",
+ params: "width=820, height=526,toolbar=1,status=1,resizable=1,scrollbars=1"
+ },
twitter: {
url: "http://twitter.com/share?url={URL}&ref=twitbtn&text={TEXT}",
params: "width=820,height=526,toolbar=1,status=1,resizable=1,scrollbars=1"
@@ -1559,11 +1569,13 @@ var socialSharing = function(){
var fb = $('a.facebook-share')
var tw = $('a.twitter-share');
var ln = $('a.linkedin-share');
+ var ica = $('a.identica-share');
copyAltToTitle(fb);
copyAltToTitle(tw);
setupButtonEventHandlers(fb, function(){share_page("facebook")});
setupButtonEventHandlers(tw, function(){share_page("twitter")});
setupButtonEventHandlers(ln, function(){share_page("linkedin")});
+ setupButtonEventHandlers(ica, function(){share_page("identica")});
}
}
}();
diff --git a/askbot/skins/default/media/js/utils.js b/askbot/skins/default/media/js/utils.js
index 9f1c3d9f..c49da02b 100644
--- a/askbot/skins/default/media/js/utils.js
+++ b/askbot/skins/default/media/js/utils.js
@@ -55,8 +55,10 @@ var showMessage = function(element, msg, where) {
var makeKeyHandler = function(key, callback){
return function(e){
if ((e.which && e.which == key) || (e.keyCode && e.keyCode == key)){
- callback();
- return false;
+ if(!e.shiftKey){
+ callback();
+ return false;
+ }
}
};
};
diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css
index c7d9eefb..7627be5e 100644
--- a/askbot/skins/default/media/style/style.css
+++ b/askbot/skins/default/media/style/style.css
@@ -1180,6 +1180,12 @@ div.comment .upvote:hover {
text-decoration: none;
}
+.comments .help-text{
+ float: right;
+ text-align:right;
+ color: gray;
+}
+
span.text-counter {
margin-right: 20px;
}
@@ -2331,7 +2337,7 @@ img.flag {
vertical-align: text-bottom;
}
-.facebook-share.icon, .twitter-share.icon, .linkedin-share.icon {
+.facebook-share.icon, .twitter-share.icon, .linkedin-share.icon, .identica-share.icon {
background: url(../images/sprite.png) no-repeat;
display:block;
text-indent:-100em;
@@ -2341,6 +2347,9 @@ img.flag {
.facebook-share.icon {
background-position: -25px 0px;
}
+.identica-share.icon {
+ background-position: -85px 0px;
+}
.twitter-share.icon {
margin-top:10px;
background-position: 0px 0px;
diff --git a/askbot/skins/default/templates/authopenid/signin.html b/askbot/skins/default/templates/authopenid/signin.html
index f3483bfa..37636207 100644
--- a/askbot/skins/default/templates/authopenid/signin.html
+++ b/askbot/skins/default/templates/authopenid/signin.html
@@ -64,7 +64,7 @@
logged_in = user.is_authenticated()
)
}}
- {% if use_password_login==True %}
+ {% if use_password_login == True %}
<fieldset
id="password-fs"
{% if user.is_anonymous() %}
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index 273ccdaf..fa15426f 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -415,17 +415,6 @@ poor design of the data or methods on data objects #}
{%- macro question_summary(question, extra_class=None) -%}
<div class="short-summary{% if extra_class %} {{extra_class}}{% endif %}">
<div class="counts">
- <div class="favorites
- {% if question.favourite_count == 0 -%}
- no-favorites
- {%else -%}
- some-favorites
- {%- endif -%}">
- <span class="item-count">{{question.favourite_count|humanize_counter}}</span>
- <div>
- {% trans cnt=question.favourite_count %}follower{% pluralize %}followers{%endtrans%}</b>
- </div>
- </div>
<div class="views
{% if question.view_count == 0 -%}
no-views
diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html
index e4d7c458..06cd1332 100644
--- a/askbot/skins/default/templates/question.html
+++ b/askbot/skins/default/templates/question.html
@@ -55,6 +55,7 @@
{% if settings.ENABLE_SHARING_TWITTER %}{{ macros.share(site = 'twitter', icon = True) }}{% endif %}
{% if settings.ENABLE_SHARING_FACEBOOK %}{{ macros.share(site = 'facebook', icon = True) }}{% endif %}
{% if settings.ENABLE_SHARING_LINKEDIN %}{{ macros.share(site = 'linkedin', icon = True) }}{% endif %}
+ {% if settings.ENABLE_SHARING_IDENTICA %}{{ macros.share(site = 'identica', icon = True) }}{% endif %}
{% if settings.ENABLE_SHARING_GOOGLE %}<g:plusone size="small" count="false"></g:plusone>{% endif %}
</div>
</td>
@@ -297,7 +298,8 @@
{% 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 %}
{% if settings.ENABLE_SHARING_LINKEDIN %}{{ macros.share(site = 'linkedin', site_label = 'LinkedIn') }},{% endif %}
- {%- if settings.ENABLE_SHARING_TWITTER or settings.ENABLE_SHARING_FACEBOOK or settings.ENABLE_SHARING_LINKEDIN -%}
+ {% if settings.ENABLE_SHARING_IDENTICA %}{{ macros.share(site = 'identica', site_label = 'Identi.ca') }},{% endif %}
+ {%- if settings.ENABLE_SHARING_TWITTER or settings.ENABLE_SHARING_FACEBOOK or settings.ENABLE_SHARING_LINKEDIN or settings.ENABLE_SHARING_IDENTICA -%}
{% trans %} or{% endtrans %}
{% endif %}
<a href="mailto:?subject={{ settings.APP_SHORT_NAME|urlencode }}&amp;body={{ question_url }}">{% trans %}email{% endtrans %}</a>.
diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py
index 3e272aa7..bb269600 100644
--- a/askbot/startup_procedures.py
+++ b/askbot/startup_procedures.py
@@ -21,6 +21,9 @@ PREAMBLE = """\n
* *
************************"""
+def askbot_warning(line):
+ print >> sys.stderr, PREAMBLE + '\n' + line
+
def format_as_text_tuple_entries(items):
"""prints out as entries or tuple containing strings
ready for copy-pasting into say django settings file"""
@@ -148,12 +151,23 @@ def test_postgres():
else:
pass #TODO: test new django dictionary databases
+def test_encoding():
+ """prints warning if encoding error is not UTF-8"""
+ if hasattr(sys.stdout, 'encoding'):
+ if sys.stdout.encoding != 'UTF-8':
+ askbot_warning(
+ 'Your output encoding is not UTF-8, there may be '
+ 'issues with the software when anything is printed '
+ 'to the terminal or log files'
+ )
+
def run_startup_tests():
"""function that runs
all startup tests, mainly checking settings config so far
"""
#todo: refactor this when another test arrives
+ test_encoding()
test_modules()
test_askbot_url()
test_i18n()
diff --git a/askbot/utils/mail.py b/askbot/utils/mail.py
index d41d666a..ae655f4c 100644
--- a/askbot/utils/mail.py
+++ b/askbot/utils/mail.py
@@ -31,6 +31,42 @@ def extract_first_email_address(text):
else:
return None
+def thread_headers(post, orig_post, update):
+ suffix_id = django_settings.SERVER_EMAIL
+ if update == const.TYPE_ACTIVITY_ASK_QUESTION:
+ id = "NQ-%s-%s" % (post.id, suffix_id)
+ headers = {'Message-ID': id}
+ elif update == const.TYPE_ACTIVITY_ANSWER:
+ id = "NA-%s-%s" % (post.id, suffix_id)
+ orig_id = "NQ-%s-%s" % (orig_post.id, suffix_id)
+ headers = {'Message-ID': id,
+ 'In-Reply-To': orig_id}
+ elif update == const.TYPE_ACTIVITY_UPDATE_QUESTION:
+ id = "UQ-%s-%s-%s" % (post.id, post.last_edited_at, suffix_id)
+ orig_id = "NQ-%s-%s" % (orig_post.id, suffix_id)
+ headers = {'Message-ID': id,
+ 'In-Reply-To': orig_id}
+ elif update == const.TYPE_ACTIVITY_COMMENT_QUESTION:
+ id = "CQ-%s-%s" % (post.id, suffix_id)
+ orig_id = "NQ-%s-%s" % (orig_post.id, suffix_id)
+ headers = {'Message-ID': id,
+ 'In-Reply-To': orig_id}
+ elif update == const.TYPE_ACTIVITY_UPDATE_ANSWER:
+ id = "UA-%s-%s-%s" % (post.id, post.last_edited_at, suffix_id)
+ orig_id = "NQ-%s-%s" % (orig_post.id, suffix_id)
+ headers = {'Message-ID': id,
+ 'In-Reply-To': orig_id}
+ elif update == const.TYPE_ACTIVITY_COMMENT_ANSWER:
+ id = "CA-%s-%s" % (post.id, suffix_id)
+ orig_id = "NQ-%s-%s" % (orig_post.id, suffix_id)
+ headers = {'Message-ID': id,
+ 'In-Reply-To': orig_id}
+ else:
+ # Unknown type -> Can't set headers
+ return {}
+
+ return headers
+
def send_mail(
subject_line = None,
body_text = None,