summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-05-06 17:58:32 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-05-06 17:58:32 -0400
commit10279a75eeee523dd16db092b9e1da424f9060dc (patch)
treea58b9df57aa0819b3731604bca291f3c2115b323
parent3cb0e5f86f1a7e06f2af669676dc8e3d2b0feb12 (diff)
downloadaskbot-10279a75eeee523dd16db092b9e1da424f9060dc.tar.gz
askbot-10279a75eeee523dd16db092b9e1da424f9060dc.tar.bz2
askbot-10279a75eeee523dd16db092b9e1da424f9060dc.zip
added "anyone can join" control to the group profile editor
-rw-r--r--askbot/skins/common/media/js/post.js27
-rw-r--r--askbot/skins/common/media/js/utils.js103
-rw-r--r--askbot/skins/default/media/bootstrap/css/bootstrap.css8
-rw-r--r--askbot/skins/default/media/style/style.less6
-rw-r--r--askbot/skins/default/templates/user_profile/user_inbox.html2
-rw-r--r--askbot/skins/default/templates/users.html6
-rw-r--r--askbot/skins/default/templates/widgets/group_info.html30
-rw-r--r--askbot/urls.py8
-rw-r--r--askbot/views/commands.py71
9 files changed, 172 insertions, 89 deletions
diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js
index 9f417642..e018197c 100644
--- a/askbot/skins/common/media/js/post.js
+++ b/askbot/skins/common/media/js/post.js
@@ -2314,15 +2314,22 @@ UserGroupProfileEditor.prototype.decorate = function(element){
var change_logo_btn = element.find('.change-logo');
this._change_logo_btn = change_logo_btn;
- var moderate_email_btn = element.find('.moderate-email');
+ var moderate_email_toggle = new TwoStateToggle();
+ moderate_email_toggle.setPostData({
+ group_id: this.getTagId(),
+ property_name: 'moderate_email'
+ });
+ var moderate_email_btn = element.find('#moderate-email');
this._moderate_email_btn = moderate_email_btn;
- var me = this;
- setupButtonEventHandlers(
- moderate_email_btn,
- function(){
- me.toggleEmailModeration();
- }
- )
+ moderate_email_toggle.decorate(moderate_email_btn);
+
+ var open_group_toggle = new TwoStateToggle();
+ open_group_toggle.setPostData({
+ group_id: this.getTagId(),
+ property_name: 'is_open'
+ });
+ var open_group_btn = element.find('#open-or-close-group');
+ open_group_toggle.decorate(open_group_btn);
var logo_changer = new ImageChanger();
logo_changer.setImageElement(element.find('.group-logo'));
@@ -2341,10 +2348,10 @@ UserGroupProfileEditor.prototype.decorate = function(element){
};
var GroupJoinButton = function(group_id){
- FollowToggle.call(this);
+ TwoStateToggle.call(this);
this._group_id = group_id;
};
-inherits(GroupJoinButton, FollowToggle);
+inherits(GroupJoinButton, TwoStateToggle);
GroupJoinButton.prototype.getPostData = function(){
return { group_id: this._group_id };
diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js
index 0c908b5d..d69777cd 100644
--- a/askbot/skins/common/media/js/utils.js
+++ b/askbot/skins/common/media/js/utils.js
@@ -481,13 +481,14 @@ DeleteIcon.prototype.setContent = function(content){
/**
* A button on which user can click
* and become added to some group (followers, group members, etc.)
+ * or toggle some state on/off
* The button has four states on-prompt, off-prompt, on-state and off-state
* on-prompt is activated on mouseover, when user is not part of group
* off-prompt - on mouseover, when user is part of group
* on-state - when user is part of group and mouse is not over the button
* off-state - same as above, but when user is not part of the group
*/
-var FollowToggle = function(){
+var TwoStateToggle = function(){
SimpleControl.call(this);
this._state = null;
this._state_messages = {};
@@ -497,10 +498,21 @@ var FollowToggle = function(){
'on-prompt',
'off-prompt'
];
+ this._handler = this.getDefaultHandler();
+ this._post_data = {};
+ this.toggleUrl = '';//public property
};
-inherits(FollowToggle, SimpleControl);
+inherits(TwoStateToggle, SimpleControl);
-FollowToggle.prototype.resetStyles = function(){
+TwoStateToggle.prototype.setPostData = function(data){
+ this._post_data = data;
+};
+
+TwoStateToggle.prototype.getPostData = function(){
+ return this._post_data;
+};
+
+TwoStateToggle.prototype.resetStyles = function(){
var element = this._element;
var states = this._states;
$.each(states, function(idx, state){
@@ -509,11 +521,11 @@ FollowToggle.prototype.resetStyles = function(){
this._element.html('');
};
-FollowToggle.prototype.isOn = function(){
+TwoStateToggle.prototype.isOn = function(){
return this._element.hasClass('on');
};
-FollowToggle.prototype.setOn = function(is_on){
+TwoStateToggle.prototype.setOn = function(is_on){
if (is_on){
this._element.addClass('on');
this._element.html(this._state_messages['on-state']);
@@ -523,35 +535,78 @@ FollowToggle.prototype.setOn = function(is_on){
}
};
-FollowToggle.prototype.setState = function(state){
+TwoStateToggle.prototype.getDefaultHandler = function(){
+ var me = this;
+ return function(){
+ var data = me.getPostData();
+ data['disable'] = me.isOn();
+ $.ajax({
+ type: 'POST',
+ dataType: 'json',
+ cache: false,
+ url: me.toggleUrl,
+ data: data,
+ success: function(data) {
+ if (data['success']) {
+ me.setOn('is_enabled');
+ } else {
+ showMessage(me.getElement(), data['message']);
+ }
+ }
+ });
+ };
+};
+
+TwoStateToggle.prototype.setState = function(state){
+ var element = this._element;
this._state = state;
- if (this._element){
- this.resetStyles();
- this._element.addClass(state);
- this._element.html(this._state_messages[state]);
+ if (element) {
+ if (
+ element.attr('nodeName') === 'INPUT' &&
+ element.attr('type') === 'checkbox'
+ ) {
+ if (state === 'on-state') {
+ element.attr('checked', true);
+ } else if (state === 'off-state') {
+ element.attr('checked', false);
+ }
+ } else {
+ this.resetStyles();
+ element.addClass(state);
+ this._element.html(this._state_messages[state]);
+ }
}
};
-FollowToggle.prototype.decorate = function(element){
+TwoStateToggle.prototype.decorate = function(element){
this._element = element;
//read messages for all states
var messages = {};
- $.each(this._states, function(idx, state){
- if (state === 'off-state'){
- return;
- }
- messages[state] = element.attr('data-' + state + '-text');
- });
- messages['off-state'] = messages['on-prompt']
+ messages['on-state'] =
+ element.attr('data-on-state-text') || gettext('enabled');
+ messages['off-state'] =
+ element.attr('data-off-state-text') || gettext('disabled');
+ messages['on-prompt'] =
+ element.attr('data-on-prompt-text') || messages['on-state'];
+ messages['off-prompt'] =
+ element.attr('data-off-prompt-text') || messages['off-state'];
this._state_messages = messages;
+ this.toggleUrl = element.attr('data-toggle-url');
+
//detect state and save it
- var text = $.trim(element.html());
- for (var i = 0; i < this._states.length; i++){
- var state = this._states[i];
- if (text === messages[state]){
- this._state = state;
- break;
+ if (
+ element.attr('nodeName') === 'INPUT' && element.attr('type', 'checkbox')
+ ) {
+ this._state = element.attr('checked') ? 'state-on' : 'state-off';
+ } else {
+ var text = $.trim(element.html());
+ for (var i = 0; i < this._states.length; i++){
+ var state = this._states[i];
+ if (text === messages[state]){
+ this._state = state;
+ break;
+ }
}
}
diff --git a/askbot/skins/default/media/bootstrap/css/bootstrap.css b/askbot/skins/default/media/bootstrap/css/bootstrap.css
index 5ffd980f..9447a9a2 100644
--- a/askbot/skins/default/media/bootstrap/css/bootstrap.css
+++ b/askbot/skins/default/media/bootstrap/css/bootstrap.css
@@ -570,7 +570,7 @@ pre code {
max-height: 340px;
overflow-y: scroll;
}
-.label {
+/*.label {
padding: 1px 4px 2px;
font-size: 10.998px;
font-weight: bold;
@@ -587,7 +587,7 @@ pre code {
.label:hover {
color: #ffffff;
text-decoration: none;
-}
+}*/
.label-important {
background-color: #b94a48;
}
@@ -3076,10 +3076,10 @@ input[type="submit"].btn.btn-mini {
display: inline-block;
padding: 5px 14px;
background-color: #fff;
- border: 1px solid #ddd;
+ /*border: 1px solid #ddd;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
- border-radius: 15px;
+ border-radius: 15px;*/
}
.pager a:hover {
text-decoration: none;
diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less
index 43f5be61..27424871 100644
--- a/askbot/skins/default/media/style/style.less
+++ b/askbot/skins/default/media/style/style.less
@@ -673,6 +673,11 @@ body.anon {
}
}
+.users-page .box label {
+ display: inline;
+ float: none;
+}
+
.statsWidget p{
color:@info-text;
font-size:16px;
@@ -2133,7 +2138,6 @@ ul#related-tags li {
.openid-signin,
.meta,
-.users-page,
.user-profile-edit-page,
{
font-size:13px;
diff --git a/askbot/skins/default/templates/user_profile/user_inbox.html b/askbot/skins/default/templates/user_profile/user_inbox.html
index ee7057e3..cda45027 100644
--- a/askbot/skins/default/templates/user_profile/user_inbox.html
+++ b/askbot/skins/default/templates/user_profile/user_inbox.html
@@ -1,7 +1,7 @@
{% extends "user_profile/user.html" %}
{% import "macros.html" as macros %}
{% block before_css %}
- <link href="{{'/bootstrap/css/bootstrap.min.css'|media}}" rel="stylesheet" type="text/css" />
+ <link href="{{'/bootstrap/css/bootstrap.css'|media}}" rel="stylesheet" type="text/css" />
{% endblock %}
<!-- user_responses.html -->
{#
diff --git a/askbot/skins/default/templates/users.html b/askbot/skins/default/templates/users.html
index 595bbd72..ec4946bb 100644
--- a/askbot/skins/default/templates/users.html
+++ b/askbot/skins/default/templates/users.html
@@ -2,6 +2,11 @@
{% import "macros.html" as macros %}
<!-- users.html -->
{% block title %}{% spaceless %}{% trans %}Users{% endtrans %}{% endspaceless %}{% endblock %}
+{% block before_css %}
+ {% if group and request.user.is_administrator() %}
+ <link href="{{'/bootstrap/css/bootstrap.css'|media}}" rel="stylesheet" type="text/css" />
+ {% endif %}
+{% endblock %}
{% block forestyle %}
<link rel="stylesheet" type="text/css" href="{{"/js/wmd/wmd.css"|media}}" />
{% endblock %}
@@ -75,7 +80,6 @@
askbot['urls']['save_tag_wiki_text'] = '{% url save_tag_wiki_text %}';
askbot['urls']['save_group_logo_url'] = '{% url save_group_logo_url %}';
askbot['urls']['delete_group_logo_url'] = '{% url delete_group_logo %}';
- askbot['urls']['toggle_group_email_moderation'] = '{% url toggle_group_email_moderation %}';
askbot['urls']['join_or_leave_group'] = '{% url join_or_leave_group %}';
</script>
<script type='text/javascript' src='{{"/js/editor.js"|media}}'></script>
diff --git a/askbot/skins/default/templates/widgets/group_info.html b/askbot/skins/default/templates/widgets/group_info.html
index b819db79..7e4b3e1e 100644
--- a/askbot/skins/default/templates/widgets/group_info.html
+++ b/askbot/skins/default/templates/widgets/group_info.html
@@ -19,6 +19,7 @@
data-off-prompt-text="{% trans %}Leave this group{% endtrans %}"
data-on-prompt-text="{% trans %}Join this group{% endtrans %}"
data-on-state-text="{% trans %}You are a member{% endtrans %}"
+ data-off-state-text="{% trans %}Join this group{% endtrans %}"
>
{% if user_is_group_member %}
{% trans %}You are a member{% endtrans %}
@@ -29,7 +30,7 @@
{% endif %}
</button>
{% endif %}
- {% if request.user.is_authenticated() and request.user.is_administrator_or_moderator() %}
+ {% if request.user.is_authenticated() and request.user.is_administrator() %}
<div class="controls">
<a class="edit-description"
>{% trans %}edit description{% endtrans %}</a>
@@ -44,16 +45,27 @@
<a class="change-logo"
>{% trans %}add logo{% endtrans %}</a>
{% endif %}
+ <br/>
{% if group_email_moderation_enabled %}
- <span>|</span>
- {% if group.group_profile.moderate_email %}
- <a class="moderate-email"
- >{% trans %}disable moderation of emailed questions{% endtrans %}</a>
- {% else %}
- <a class="moderate-email"
- >{% trans %}moderate emailed questions{% endtrans %}</a>
- {% endif %}
+ <input type="checkbox"
+ id="moderate-email"
+ {% if group.group_profile.moderate_email %}checked="checked"{% endif %}
+ data-toggle-url="{% url toggle_group_profile_property %}"
+ />
+ <label for="moderate-email">
+ {% trans %}moderate emailed questions{% endtrans %}
+ </label>
+ <br/>
{% endif %}
+ <input type="checkbox"
+ id="open-or-close-group"
+ {% if group.group_profile.is_open %}checked="checked"{% endif %}
+ data-toggle-url="{% url toggle_group_profile_property %}"
+ />
+ <label for="open-or-close-group">
+ {% trans %}anyone can join{% endtrans %}
+ </label>
+ <br/>
</div>
{% endif %}
</div>
diff --git a/askbot/urls.py b/askbot/urls.py
index 7a3eb248..fb9ea977 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -213,9 +213,9 @@ urlpatterns = patterns('',
name = 'delete_group_logo'
),
url(#ajax only
- r'^toggle-group-email-moderation/',
- views.commands.toggle_group_email_moderation,
- name = 'toggle_group_email_moderation'
+ r'^toggle-group-profile-property/',
+ views.commands.toggle_group_profile_property,
+ name = 'toggle_group_profile_property'
),
url(
r'^get-groups-list/',
@@ -311,7 +311,7 @@ urlpatterns = patterns('',
url(#ajax only
r'^join-or-leave-group/$',
views.commands.join_or_leave_group,
- name='join_or_leave_group'
+ name = 'join_or_leave_group'
),
url(
r'^feeds/(?P<url>.*)/$',
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 6825461e..4a560f1e 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -10,7 +10,7 @@ from django.core import exceptions
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponseBadRequest
-from django.forms import ValidationError, IntegerField
+from django.forms import ValidationError, IntegerField, CharField
from django.shortcuts import get_object_or_404
from django.views.decorators import csrf
from django.utils import simplejson
@@ -731,32 +731,6 @@ def read_message(request):#marks message a read
@csrf.csrf_exempt
@decorators.ajax_only
@decorators.post_only
-def join_or_leave_group(request):
- """only current user can join/leave group"""
- if request.user.is_anonymous():
- raise exceptions.PermissionDenied()
-
- group_id = IntegerField().clean(request.POST['group_id'])
- group = models.Tag.objects.get(id = group_id)
-
- if request.user.is_group_member(group):
- action = 'remove'
- is_member = False
- else:
- action = 'add'
- is_member = True
- request.user.edit_group_membership(
- user = request.user,
- group = group,
- action = action
- )
- return {'is_member': is_member}
-
-
-
-@csrf.csrf_exempt
-@decorators.ajax_only
-@decorators.post_only
@decorators.admins_only
def edit_group_membership(request):
form = forms.EditGroupMembershipForm(request.POST)
@@ -821,6 +795,7 @@ def delete_group_logo(request):
group.group_profile.logo_url = None
group.group_profile.save()
+
@csrf.csrf_exempt
@decorators.ajax_only
@decorators.post_only
@@ -830,21 +805,47 @@ def delete_post_reject_reason(request):
reason = models.PostFlagReason.objects.get(id = reason_id)
reason.delete()
+
@csrf.csrf_exempt
@decorators.ajax_only
@decorators.post_only
@decorators.admins_only
-def toggle_group_email_moderation(request):
+def toggle_group_profile_property(request):
+ #todo: this might be changed to more general "toggle object property"
group_id = IntegerField().clean(int(request.POST['group_id']))
- group = models.Tag.group_tags.get(id = group_id)
- group.group_profile.moderate_email = not group.group_profile.moderate_email
+ property_name = CharField().clean(request.POST['property_name'])
+ assert property_name in ('is_open', 'moderate_email')
+
+ group = models.Tag.objects.get(id = group_id)
+ new_value = not getattr(group.group_profile, property_name)
+ setattr(group.group_profile, property_name, new_value)
group.group_profile.save()
- if group.group_profile.moderate_email:
- new_button_text = _('disable moderation of emailed questions')
- else:
- new_button_text = _('moderate emailed questions')
- return {'new_button_text': new_button_text}
+ return {'is_enabled': new_value}
+
+
+@csrf.csrf_exempt
+@decorators.ajax_only
+@decorators.post_only
+def join_or_leave_group(request):
+ """only current user can join/leave group"""
+ if request.user.is_anonymous():
+ raise exceptions.PermissionDenied()
+ group_id = IntegerField().clean(request.POST['group_id'])
+ group = models.Tag.objects.get(id = group_id)
+
+ if request.user.is_group_member(group):
+ action = 'remove'
+ is_member = False
+ else:
+ action = 'add'
+ is_member = True
+ request.user.edit_group_membership(
+ user = request.user,
+ group = group,
+ action = action
+ )
+ return {'is_member': is_member}
@csrf.csrf_exempt