summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-03-20 21:37:05 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2012-03-20 21:38:33 -0400
commit362d4c3074983b6dbc5e420b7b4f4ebd8f1d380d (patch)
treedada135ee5b27a65c451c45f4c5f20041cfb1e96
parent2ab9a079954a11a9dcf8bac7dbc9454d32054e7b (diff)
downloadaskbot-362d4c3074983b6dbc5e420b7b4f4ebd8f1d380d.tar.gz
askbot-362d4c3074983b6dbc5e420b7b4f4ebd8f1d380d.tar.bz2
askbot-362d4c3074983b6dbc5e420b7b4f4ebd8f1d380d.zip
user groups are deletable, commit from the bus en route to Cordoba
-rw-r--r--askbot/forms.py13
-rw-r--r--askbot/models/__init__.py18
-rw-r--r--askbot/models/tag.py10
-rw-r--r--askbot/skins/common/media/js/user.js110
-rw-r--r--askbot/skins/common/media/js/utils.js16
-rw-r--r--askbot/skins/default/media/style/style.less21
-rw-r--r--askbot/skins/default/templates/user_profile/user.html2
-rw-r--r--askbot/urls.py6
-rw-r--r--askbot/views/commands.py22
9 files changed, 186 insertions, 32 deletions
diff --git a/askbot/forms.py b/askbot/forms.py
index ebb1b519..45b722cc 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -1136,6 +1136,17 @@ class SimpleEmailSubscribeForm(forms.Form):
email_settings_form = EFF(initial=EFF.NO_EMAIL_INITIAL)
email_settings_form.save(user, save_unbound=True)
-class AddUserToGroupForm(forms.Form):
+class EditGroupMembershipForm(forms.Form):
+ """a form for adding or removing users
+ to and from user groups"""
user_id = forms.IntegerField()
group_name = forms.CharField()
+ action = forms.CharField()
+
+ def clean_action(self):
+ """allowed actions are 'add' and 'remove'"""
+ action = self.cleaned_data['action']
+ if action not in ('add', 'remove'):
+ del self.cleaned_data['action']
+ raise forms.ValidationError('invalid action')
+ return action
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index bbda51bc..7ad46619 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -2174,10 +2174,20 @@ def user_update_wildcard_tag_selections(
return new_tags
-def user_add_user_to_group(self, user = None, group = None):
- """allows one user to add another to a pre-existing group"""
- GroupMembership.objects.get_or_create(user = user, group = group)
+def user_edit_group_membership(self, user = None, group = None, action = None):
+ """allows one user to add another to a group
+ or remove user from group.
+ If when adding, the group does not exist, it will be created
+ the delete function is not symmetric, the group will remain
+ even if it becomes empty
+ """
+ if action == 'add':
+ GroupMembership.objects.get_or_create(user = user, group = group)
+ elif action == 'remove':
+ GroupMembership.objects.get(user = user, group = group).delete()
+ else:
+ raise ValueError('invalid action')
User.add_to_class(
'add_missing_askbot_subscriptions',
@@ -2241,7 +2251,7 @@ User.add_to_class('can_post_comment', user_can_post_comment)
User.add_to_class('is_administrator', user_is_administrator)
User.add_to_class('is_administrator_or_moderator', user_is_administrator_or_moderator)
User.add_to_class('set_admin_status', user_set_admin_status)
-User.add_to_class('add_user_to_group', user_add_user_to_group)
+User.add_to_class('edit_group_membership', user_edit_group_membership)
User.add_to_class('remove_admin_status', user_remove_admin_status)
User.add_to_class('is_moderator', user_is_moderator)
User.add_to_class('is_approved', user_is_approved)
diff --git a/askbot/models/tag.py b/askbot/models/tag.py
index 097c2df9..6e92bab9 100644
--- a/askbot/models/tag.py
+++ b/askbot/models/tag.py
@@ -86,6 +86,11 @@ class TagManager(BaseQuerySetManager):
#class GroupTagQuerySet(models.query.QuerySet):
# """Custom query set for the group"""
# def __init__(self, model):
+def clean_group_name(name):
+ """group names allow spaces,
+ tag names do not, so we use this method
+ to replace spaces with dashes"""
+ return re.sub('\s+', '-', name.strip())
class GroupTagManager(TagManager):
"""manager for group tags"""
@@ -98,7 +103,7 @@ class GroupTagManager(TagManager):
#todo: here we might fill out the group profile
#replace spaces with dashes
- group_name = re.sub('\s+', '-', group_name.strip())
+ group_name = clean_group_name(group_name)
try:
tag = self.get(name = group_name)
except self.model.DoesNotExist:
@@ -118,6 +123,9 @@ class GroupTagManager(TagManager):
member_count__gt = 0
)
+ def get_by_name(self, group_name = None):
+ return self.get(name = clean_group_name(group_name))
+
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
created_by = models.ForeignKey(User, related_name='created_tags')
diff --git a/askbot/skins/common/media/js/user.js b/askbot/skins/common/media/js/user.js
index aed926d1..feab4d27 100644
--- a/askbot/skins/common/media/js/user.js
+++ b/askbot/skins/common/media/js/user.js
@@ -222,36 +222,114 @@ FollowUser.prototype.toggleState = function(){
/**
* @constructor
+ * @param {string} name
*/
-GroupsContainer = function(){
+var UserGroup = function(name){
+ WrappedElement.call(this);
+ this._name = name;
+};
+inherits(UserGroup, WrappedElement);
+
+UserGroup.prototype.getDeleteHandler = function(){
+ var group_name = this._name;
+ var me = this;
+ var groups_container = me._groups_container;
+ return function(){
+ var data = {
+ user_id: askbot['data']['viewUserId'],
+ group_name: group_name,
+ action: 'remove'
+ };
+ $.ajax({
+ type: 'POST',
+ dataType: 'json',
+ data: data,
+ cache: false,
+ url: askbot['urls']['edit_group_membership'],
+ success: function(){
+ groups_container.removeGroup(me);
+ }
+ });
+ };
+};
+
+UserGroup.prototype.getName = function(){
+ return this._name;
+};
+
+UserGroup.prototype.setGroupsContainer = function(container){
+ this._groups_container = container;
+};
+
+UserGroup.prototype.decorate = function(element){
+ this._element = element;
+ this._name = $.trim(element.html());
+ var deleter = new DeleteIcon();
+ deleter.setHandler(this.getDeleteHandler());
+ deleter.setContent('x');
+ this._element.append(deleter.getElement());
+ this._delete_icon = deleter;
+};
+
+UserGroup.prototype.createDom = function(){
+ var element = this.makeElement('li');
+ element.html(this._name + ' ');
+ this._element = element;
+ this.decorate(element);
+};
+
+UserGroup.prototype.dispose = function(){
+ this._delete_icon.dispose();
+ this._element.remove();
+};
+
+/**
+ * @constructor
+ */
+var GroupsContainer = function(){
WrappedElement.call(this);
};
inherits(GroupsContainer, WrappedElement);
GroupsContainer.prototype.decorate = function(element){
this._element = element;
- var groups = {};
+ var groups = [];
+ var group_names = [];
+ var me = this;
//collect list of groups
$.each(element.find('li'), function(idx, li){
- groups[$(li).html()] = 1;
- //var str = $(li).html();
- //var bytes = [];
- //for (var i = 0; i<str.length; i++){
- //}
+ var group = new UserGroup();
+ group.setGroupsContainer(me);
+ group.decorate($(li));
+ groups.push(group);
+ group_names.push(group.getName());
});
this._groups = groups;
+ this._group_names = group_names;
};
GroupsContainer.prototype.addGroup = function(group_name){
- if (group_name in this._groups){
+ if ($.inArray(group_name, this._group_names) > -1){
return;
}
- var group = this.makeElement('li');
- group.html(group_name);
- this._element.append(group);
+ var group = new UserGroup(group_name);
+ group.setGroupsContainer(this);
+ this._groups.push(group);
+ this._group_names.push(group_name);
+ this._element.append(group.getElement());
};
-GroupAdderWidget = function(){
+GroupsContainer.prototype.removeGroup = function(group){
+ var idx = $.inArray(group, this._groups);
+ if (idx === -1){
+ return;
+ }
+ this._groups.splice(idx, 1);
+ this._group_names.splice(idx, 1);
+ group.dispose();
+};
+
+var GroupAdderWidget = function(){
WrappedElement.call(this);
this._state = 'display';//display or edit
};
@@ -291,14 +369,15 @@ GroupAdderWidget.prototype.getAddGroupHandler = function(){
var group_name = me.getValue();
var data = {
group_name: group_name,
- user_id: askbot['data']['viewUserId']
+ user_id: askbot['data']['viewUserId'],
+ action: 'add'
};
$.ajax({
type: 'POST',
dataType: 'json',
data: data,
cache: false,
- url: askbot['urls']['add_user_to_group'],
+ url: askbot['urls']['edit_group_membership'],
success: function(data){
if (data['success'] == true){
me.addGroup(group_name);
@@ -358,7 +437,7 @@ GroupAdderWidget.prototype.decorate = function(element){
* @constructor
* allows editing user groups
*/
-UserGroupsEditor = function(){
+var UserGroupsEditor = function(){
WrappedElement.call(this);
};
inherits(UserGroupsEditor, WrappedElement);
@@ -389,4 +468,3 @@ UserGroupsEditor.prototype.decorate = function(element){
$('#add-group').remove();
}
})();
-
diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js
index 9e02b5d4..3a6fbfe5 100644
--- a/askbot/skins/common/media/js/utils.js
+++ b/askbot/skins/common/media/js/utils.js
@@ -240,6 +240,9 @@ WrappedElement.prototype.setElement = function(element){
WrappedElement.prototype.createDom = function(){
this._element = $('<div></div>');
};
+WrappedElement.prototype.decorate = function(element){
+ this._element = element;
+};
WrappedElement.prototype.getElement = function(){
if (this._element === null){
this.createDom();
@@ -308,6 +311,7 @@ EditLink.prototype.decorate = function(element){
var DeleteIcon = function(title){
SimpleControl.call(this);
this._title = title;
+ this._content = null;
};
inherits(DeleteIcon, SimpleControl);
@@ -327,8 +331,20 @@ DeleteIcon.prototype.setHandlerInternal = function(){
DeleteIcon.prototype.createDom = function(){
this._element = this.makeElement('span');
this.decorate(this._element);
+ if (this._content !== null){
+ this.setContent(this._content);
+ }
};
+DeleteIcon.prototype.setContent = function(content){
+ if (this._element === null){
+ this._content = content;
+ } else {
+ this._content = content;
+ this._element.html(content);
+ }
+}
+
var Tag = function(){
SimpleControl.call(this);
this._deletable = false;
diff --git a/askbot/skins/default/media/style/style.less b/askbot/skins/default/media/style/style.less
index e63ff373..41e42d68 100644
--- a/askbot/skins/default/media/style/style.less
+++ b/askbot/skins/default/media/style/style.less
@@ -3383,3 +3383,24 @@ body.anon.lang-es {
}
}
}
+
+/* user groups */
+#user-groups ul {
+ margin-bottom: 0px;
+}
+#user-groups .delete-icon {
+ float: none;
+ display: inline;
+ color: #525252;
+ padding: 0 3px 0 3px;
+ background: #ccc;
+ border-radius: 4px;
+ line-height:inherit;
+ -moz-border-radius: 4px;
+ -khtml-border-radius: 4px;
+ -webkit-border-radius: 4px;
+}
+#user-groups .delete-icon:hover {
+ color: white;
+ background: #b32f2f;
+}
diff --git a/askbot/skins/default/templates/user_profile/user.html b/askbot/skins/default/templates/user_profile/user.html
index f204d338..15e0622a 100644
--- a/askbot/skins/default/templates/user_profile/user.html
+++ b/askbot/skins/default/templates/user_profile/user.html
@@ -23,7 +23,7 @@
var viewUserID = {{view_user.id}};
askbot['data']['viewUserName'] = '{{ view_user.username }}';
askbot['data']['viewUserId'] = {{view_user.id}};
- askbot['urls']['add_user_to_group'] = '{% url add_user_to_group %}';
+ askbot['urls']['edit_group_membership'] = '{% url edit_group_membership %}';
askbot['urls']['get_groups_list'] = '{% url get_groups_list %}';
</script>
{% if request.user|can_moderate_user(view_user) %}
diff --git a/askbot/urls.py b/askbot/urls.py
index 1cc51be3..a920ee6a 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -258,9 +258,9 @@ urlpatterns = patterns('',
name='manage_inbox'
),
url(#ajax only
- r'^add_user_to_group/$',
- views.commands.add_user_to_group,
- name='add_user_to_group'
+ r'^edit-group-membership/$',
+ views.commands.edit_group_membership,
+ name='edit_group_membership'
),
url(
r'^feeds/(?P<url>.*)/$',
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 2a7f9a0a..8d0fdda9 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -656,16 +656,16 @@ def read_message(request):#marks message a read
@csrf.csrf_exempt
@decorators.ajax_only
@decorators.post_only
-def add_user_to_group(request):
+def edit_group_membership(request):
if request.user.is_anonymous():
raise exceptions.PermissionDenied()
if not request.user.is_administrator_or_moderator():
raise exceptions.PermissionDenied(
- _('Only moderators and administrators can assign users to groups')
+ _('Only moderators and administrators can change user groups')
)
- form = forms.AddUserToGroupForm(request.POST)
+ form = forms.EditGroupMembershipForm(request.POST)
if form.is_valid():
group_name = form.cleaned_data['group_name']
user_id = form.cleaned_data['user_id']
@@ -676,8 +676,18 @@ def add_user_to_group(request):
'user with id %d not found' % user_id
)
- group_params = {'group_name': group_name, 'user': user}
- group = models.Tag.group_tags.get_or_create(**group_params)
- request.user.add_user_to_group(user, group)
+ action = form.cleaned_data['action']
+ if action == 'add':
+ group_params = {'group_name': group_name, 'user': user}
+ group = models.Tag.group_tags.get_or_create(**group_params)
+ request.user.edit_group_membership(user, group, 'add')
+ elif action == 'remove':
+ try:
+ group = models.Tag.group_tags.get_by_name(group_name = group_name)
+ request.user.edit_group_membership(user, group, 'remove')
+ except models.Tag.DoesNotExist:
+ raise exceptions.PermissionDenied()
+ else:
+ raise exceptions.PermissionDenied()
else:
raise exceptions.PermissionDenied()