diff options
-rw-r--r-- | askbot/conf/minimum_reputation.py | 9 | ||||
-rw-r--r-- | askbot/conf/settings_wrapper.py | 4 | ||||
-rw-r--r-- | askbot/conf/site_modes.py | 1 | ||||
-rw-r--r-- | askbot/doc/source/changelog.rst | 1 | ||||
-rw-r--r-- | askbot/media/js/utils.js | 142 | ||||
-rw-r--r-- | askbot/media/style/style.css | 35 | ||||
-rw-r--r-- | askbot/media/style/style.less | 32 | ||||
-rw-r--r-- | askbot/templates/meta/bottom_scripts.html | 5 | ||||
-rw-r--r-- | askbot/templates/widgets/user_long_score_and_badge_summary.html | 6 | ||||
-rw-r--r-- | askbot/templates/widgets/user_perms.html | 28 | ||||
-rw-r--r-- | askbot/urls.py | 7 | ||||
-rw-r--r-- | askbot/views/readers.py | 62 | ||||
-rw-r--r-- | askbot/views/users.py | 1 |
13 files changed, 318 insertions, 15 deletions
diff --git a/askbot/conf/minimum_reputation.py b/askbot/conf/minimum_reputation.py index 229edf96..19b5e69d 100644 --- a/askbot/conf/minimum_reputation.py +++ b/askbot/conf/minimum_reputation.py @@ -195,15 +195,6 @@ settings.register( settings.register( livesettings.IntegerValue( MIN_REP, - 'MIN_REP_TO_LOCK_POSTS', - default=400, - description=_('Lock posts') - ) -) - -settings.register( - livesettings.IntegerValue( - MIN_REP, 'MIN_REP_TO_HAVE_STRONG_URL', default=25, description=_('Remove rel=nofollow from own homepage'), diff --git a/askbot/conf/settings_wrapper.py b/askbot/conf/settings_wrapper.py index b6b5f302..0a4ba45f 100644 --- a/askbot/conf/settings_wrapper.py +++ b/askbot/conf/settings_wrapper.py @@ -53,6 +53,10 @@ class ConfigSettings(object): """return the defalut value for the setting""" return getattr(self.__instance, key).default + def get_description(self, key): + """returns descriptive title of the setting""" + return unicode(getattr(self.__instance, key).description) + def reset(self, key): """returns setting to the default value""" self.update(key, self.get_default(key)) diff --git a/askbot/conf/site_modes.py b/askbot/conf/site_modes.py index 7c81341e..feadd32b 100644 --- a/askbot/conf/site_modes.py +++ b/askbot/conf/site_modes.py @@ -27,7 +27,6 @@ LARGE_SITE_MODE_SETTINGS = { 'MIN_REP_TO_EDIT_OTHERS_POSTS': 2000, 'MIN_REP_TO_VIEW_OFFENSIVE_FLAGS': 2000, 'MIN_REP_TO_CLOSE_OTHERS_QUESTIONS': 2000, - 'MIN_REP_TO_LOCK_POSTS': 4000, 'MIN_REP_TO_HAVE_STRONG_URL': 250, #badge settings 'NOTABLE_QUESTION_BADGE_MIN_VIEWS': 250, diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst index 6d14dd36..85a7015e 100644 --- a/askbot/doc/source/changelog.rst +++ b/askbot/doc/source/changelog.rst @@ -3,6 +3,7 @@ Changes in Askbot Development version ------------------- +* Added hovercard on the user's karma display in the header * Added option to hide ad blocks from logged in users * Applied Askbot templates to the settings control panel * Added option to auto-follow questions by the question posters with default "on" diff --git a/askbot/media/js/utils.js b/askbot/media/js/utils.js index 99d70466..51e3b7ba 100644 --- a/askbot/media/js/utils.js +++ b/askbot/media/js/utils.js @@ -2325,6 +2325,148 @@ Tag.prototype.createDom = function(){ } }; +var PermsHoverCard = function() { + WrappedElement.call(this); + this._isLoaded = false; +}; +inherits(PermsHoverCard, WrappedElement); + +PermsHoverCard.prototype.setContent = function(data) { + this._element.html(data['html']); +}; + +PermsHoverCard.prototype.setTrigger = function(trigger) { + this._trigger = trigger; +}; + +PermsHoverCard.prototype.setPosition = function() { + var trigger = this._trigger.getElement(); + var coors = trigger.offset(); + var height = trigger.outerHeight(); + var triangle = this._element.find('.triangle') + var triangleHeight = triangle.outerHeight(); + this._element.css({ + 'top': coors.top + height + triangleHeight, + 'left': coors.left + }); +}; + +PermsHoverCard.prototype.setUrl = function(url) { + this._url = url; +}; + +PermsHoverCard.prototype.startLoading = function(onLoad) { + var me = this; + $.ajax({ + type: 'GET', + dataType: 'json', + cache: false, + url: this._url, + success: function(data) { + if (data['success']) { + me.setContent(data); + me.setPosition(); + onLoad(); + me.setIsLoaded(); + } else { + notify.show(data['message']); + } + } + }); +}; + +PermsHoverCard.prototype.isLoaded = function() { + return this._isLoaded; +}; + +PermsHoverCard.prototype.setIsLoaded = function() { + this._isLoaded = true; +}; + +PermsHoverCard.prototype.getOpenHandler = function() { + var me = this; + return function() { + me.clearCancelOpenTimeout(); + if (me.isLoaded()) { + me.getElement().show(); + } else { + var onload = function() { + me.getElement().show(); + } + me.startLoading(onload); + } + }; +}; + +PermsHoverCard.prototype.setCancelOpenTimoutId = function(timeoutId) { + this._cancelOpenTimeoutId = timeoutId; +}; + +PermsHoverCard.prototype.clearCancelOpenTimeout = function() { + var timeout = this._cancelOpenTimeoutId; + if (timeout) { + clearTimeout(timeout); + } +}; + +PermsHoverCard.prototype.getCloseHandler = function() { + var me = this; + return function() { + var element = me.getElement(); + //start timeout to close + var timeout = setTimeout(function() { + element.hide(); + //element.fadeOut('fast'); + }, 200); + me.setCancelOpenTimoutId(timeout); + }; +}; + +PermsHoverCard.prototype.getImmediateCloseHandler = function() { + var me = this; + return function() { + me.getElement().hide(); + }; +}; + +PermsHoverCard.prototype.getKeepHandler = function() { + var me = this; + return function() { + me.clearCancelOpenTimeout(); + }; +}; + +PermsHoverCard.prototype.createDom = function() { + var element = this.makeElement('div'); + this._element = element; + element.addClass('hovercard'); + element.hover( + this.getKeepHandler(), + this.getCloseHandler() + ); +}; + +var ShowPermsTrigger = function() { + WrappedElement.call(this); +}; +inherits(ShowPermsTrigger, WrappedElement); + +ShowPermsTrigger.prototype.decorate = function(element) { + this._element = element; + var hoverCard = new PermsHoverCard(); + this._hoverCard = hoverCard; + $('body').append(hoverCard.getElement()); + + hoverCard.setTrigger(this); + hoverCard.setUrl(element.data('url')); + + var onEnter = hoverCard.getOpenHandler(); + var onExit = hoverCard.getCloseHandler(); + element.hover(onEnter, onExit); + var onClose = hoverCard.getImmediateCloseHandler(); + $('body').click(onClose); +}; + //Search Engine Keyword Highlight with Javascript //http://scott.yang.id.au/code/se-hilite/ Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["local","q"],["cnprog\\.","q"],["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}}; diff --git a/askbot/media/style/style.css b/askbot/media/style/style.css index 2a8968f4..7154a05b 100644 --- a/askbot/media/style/style.css +++ b/askbot/media/style/style.css @@ -218,6 +218,37 @@ body.user-messages { text-align: center; margin: 5px 0 8px; } +.hovercard { + background: white; + border: 1px solid #aaa; + -webkit-box-shadow: 0 0 1px #929292; + -moz-box-shadow: 0 0 1px #929292; + box-shadow: 0 0 1px #929292; + font-size: 13px; + display: block; + max-width: 250px; + padding: 10px; + position: absolute; +} +.hovercard p:last-child { + margin-bottom: 0; +} +.hovercard ul { + margin-bottom: 0; +} +.hovercard ul li { + font-size: 13px; + line-height: 16px; + margin: 5px 0; +} +.hovercard .triangle { + border-left: 5px solid transparent; + border-right: 10px solid transparent; + border-bottom: 10px solid #fcfcfc; + height: 0; + margin: -20px 0 10px 0; + width: 0; +} #closeNotify { position: absolute; right: 5px; @@ -2248,7 +2279,9 @@ ul#related-tags li { line-height: 18px; margin-top: -2px; margin-left: 4px; - box-shadow: none; + -webkit-box-shadow: 0 0 0 #929292; + -moz-box-shadow: 0 0 0 #929292; + box-shadow: 0 0 0 #929292; } .question-page .post-controls .answer-convert input:hover, .question-page .answer-controls .answer-convert input:hover { diff --git a/askbot/media/style/style.less b/askbot/media/style/style.less index 31773b21..c1a64bb1 100644 --- a/askbot/media/style/style.less +++ b/askbot/media/style/style.less @@ -232,6 +232,36 @@ body.user-messages { margin: 5px 0 8px; } +.hovercard { + background: white; + border: 1px solid #aaa; + .box-shadow(0, 0, 1px); + font-size: 13px; + display: block; + max-width: 250px; + padding: 10px; + position: absolute; + p:last-child { + margin-bottom: 0; + } + ul { + margin-bottom: 0; + li { + font-size: 13px; + line-height: 16px; + margin: 5px 0; + } + } + .triangle { + border-left: 5px solid transparent; + border-right: 10px solid transparent; + border-bottom: 10px solid #fcfcfc; + height: 0; + margin: -20px 0 10px 0; + width: 0; + } +} + #closeNotify { position: absolute; right: 5px; @@ -2364,7 +2394,7 @@ ul#related-tags li { line-height:18px; margin-top:-2px; margin-left:4px; - box-shadow: none; + .box-shadow(0, 0, 0); } .answer-convert input:hover{ diff --git a/askbot/templates/meta/bottom_scripts.html b/askbot/templates/meta/bottom_scripts.html index e707b29f..5c398358 100644 --- a/askbot/templates/meta/bottom_scripts.html +++ b/askbot/templates/meta/bottom_scripts.html @@ -98,6 +98,11 @@ var group_dropdown = new GroupDropdown({{ group_list }}); $('.dropdown').append(group_dropdown.getElement()); } + var userRep = $('#userToolsNav .reputation'); + if (userRep.length) { + var showPermsTrigger = new ShowPermsTrigger(); + showPermsTrigger.decorate(userRep); + } }); if (askbot['data']['haveFlashNotifications']) { $('#validate_email_alert').click(function(){notify.close(true)}) diff --git a/askbot/templates/widgets/user_long_score_and_badge_summary.html b/askbot/templates/widgets/user_long_score_and_badge_summary.html index 35e4cb67..771a8f3f 100644 --- a/askbot/templates/widgets/user_long_score_and_badge_summary.html +++ b/askbot/templates/widgets/user_long_score_and_badge_summary.html @@ -1,7 +1,9 @@ {% set have_badges = user.gold or user.silver or user.bronze %} {%- if karma_mode != 'hidden' -%} -<a class="user-micro-info" - href="{{user.get_absolute_url()}}?sort=reputation" +<a + class="user-micro-info reputation" + href="{{user.get_absolute_url()}}?sort=reputation" + data-url="{% url 'get_perms_data' %}" >{% trans %}karma:{% endtrans %} {{user.reputation}}</a>{% if badges_mode == 'public' and have_badges %},{% endif %} {%- endif -%} {% if badges_mode == 'public' and have_badges %} diff --git a/askbot/templates/widgets/user_perms.html b/askbot/templates/widgets/user_perms.html new file mode 100644 index 00000000..a51a8882 --- /dev/null +++ b/askbot/templates/widgets/user_perms.html @@ -0,0 +1,28 @@ +<!--h2>{% trans karma=user.reputation %}Your karma is {{ karma }}{% endtrans %}</h2--> +<div class="triangle"></div> +<p> + {% trans %}Karma reflects how valuable is your contribution to this community.{% endtrans %} +</p> +<p> + {% if user.is_administrator_or_moderator() %} + {% if user.is_moderator() %} + {% set role=gettext('moderator') %} + {% else %} + {% set role=gettext('administrator') %} + {% endif %} + {% trans %}Since you are the site {{ role }}, you have access to all functions regardless of your karma.{% endtrans %} + {% else %} + {% trans %}The higher is your karma, the more rights you have on this site.{% endtrans %} + {% endif %} +</p> +{% if not user.is_administrator_or_moderator() %} +<p> {% trans %}Currently, you can:{% endtrans %}</p> +<ul> + <li>{% trans %}Post questions, answers and comments{% endtrans %}</li> + {% for perm in perms_data %} + {% if user.reputation >= perm[1] %} + <li>{{ perm[0] }}</li> + {% endif %} + {% endfor %} +</ul> +{% endif %} diff --git a/askbot/urls.py b/askbot/urls.py index f71962f1..e82ad0df 100644 --- a/askbot/urls.py +++ b/askbot/urls.py @@ -534,7 +534,12 @@ urlpatterns = patterns('', service_url( r'^widgets/questions/(?P<widget_id>\d+)/$', views.widgets.question_widget, - name = 'question_widget' + name='question_widget' + ), + service_url( + r'^get-perms-data/$', + views.readers.get_perms_data, + name='get_perms_data' ), service_url( r'^start-sharing-twitter/$', diff --git a/askbot/views/readers.py b/askbot/views/readers.py index f738da25..b2a27324 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -638,3 +638,65 @@ def get_comment(request): comment = models.Post.objects.get(post_type='comment', id=id) request.user.assert_can_edit_comment(comment) return {'text': comment.text} + + +@csrf.csrf_exempt +@ajax_only +@anonymous_forbidden +@get_only +def get_perms_data(request): + """returns details about permitted activities + according to the users reputation + """ + + items = ( + 'MIN_REP_TO_VOTE_UP', + 'MIN_REP_TO_VOTE_DOWN', + ) + + if askbot_settings.MIN_DAYS_TO_ANSWER_OWN_QUESTION > 0: + items += ('MIN_REP_TO_ANSWER_OWN_QUESTION',) + + if askbot_settings.ACCEPTING_ANSWERS_ENABLED: + items += ( + 'MIN_REP_TO_ACCEPT_OWN_ANSWER', + 'MIN_REP_TO_ACCEPT_ANY_ANSWER', + ) + + items += ( + 'MIN_REP_TO_FLAG_OFFENSIVE', + 'MIN_REP_TO_DELETE_OTHERS_COMMENTS', + 'MIN_REP_TO_DELETE_OTHERS_POSTS', + 'MIN_REP_TO_UPLOAD_FILES', + 'MIN_REP_TO_INSERT_LINK', + 'MIN_REP_TO_SUGGEST_LINK', + 'MIN_REP_TO_CLOSE_OWN_QUESTIONS', + 'MIN_REP_TO_REOPEN_OWN_QUESTIONS', + 'MIN_REP_TO_CLOSE_OTHERS_QUESTIONS', + 'MIN_REP_TO_RETAG_OTHERS_QUESTIONS', + 'MIN_REP_TO_EDIT_WIKI', + 'MIN_REP_TO_EDIT_OTHERS_POSTS', + 'MIN_REP_TO_VIEW_OFFENSIVE_FLAGS', + ) + + if askbot_settings.ALLOW_ASKING_BY_EMAIL or askbot_settings.REPLY_BY_EMAIL: + items += ( + 'MIN_REP_TO_POST_BY_EMAIL', + 'MIN_REP_TO_TWEET_ON_OTHERS_ACCOUNTS', + ) + + data = list() + for item in items: + setting = ( + askbot_settings.get_description(item), + getattr(askbot_settings, item) + ) + data.append(setting) + + template = get_template('widgets/user_perms.html') + html = template.render({ + 'user': request.user, + 'perms_data': data + }) + + return {'html': html} diff --git a/askbot/views/users.py b/askbot/views/users.py index 179392d2..c58b5abd 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -60,6 +60,7 @@ def owner_or_moderator_required(f): return f(request, profile_owner, context) return wrapped_func + def show_users(request, by_group=False, group_id=None, group_slug=None): """Users view, including listing of users by group""" if askbot_settings.GROUPS_ENABLED and not by_group: |