Skip to content

Commit

Permalink
Merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
johnmartin committed Nov 14, 2012
2 parents 819d192 + 8cdd117 commit f6026f9
Show file tree
Hide file tree
Showing 27 changed files with 1,301 additions and 458 deletions.
5 changes: 5 additions & 0 deletions ckan/config/routing.py
Expand Up @@ -238,6 +238,11 @@ def make_map():
'authz',
'delete',
'history',
'followers',
'follow',
'unfollow',
'admins',
'about',
'activity',
]))
)
Expand Down
75 changes: 71 additions & 4 deletions ckan/controllers/group.py
Expand Up @@ -129,10 +129,12 @@ def read(self, id):
_("Cannot render description")
c.description_formatted = genshi.HTML(error_msg)

c.group_admins = self.authorizer.get_admins(c.group)

context['return_query'] = True

# c.group_admins is used by CKAN's legacy (Genshi) templates only,
# if we drop support for those then we can delete this line.
c.group_admins = self.authorizer.get_admins(c.group)

limit = 20
try:
page = int(request.params.get('page', 1))
Expand Down Expand Up @@ -511,11 +513,76 @@ def activity(self, id):

# Add the group's activity stream (already rendered to HTML) to the
# template context for the group/read.html template to retrieve later.
c.group_activity_stream = get_action('group_activity_list_html')(
context, {'id': c.group_dict['id']})
c.group_activity_stream = \
get_action('group_activity_list_html')(context,
{'id': c.group_dict['id']})

return render('group/activity_stream.html')

def follow(self, id):
'''Start following this group.'''
context = {'model': model,
'session': model.Session,
'user': c.user or c.author}
data_dict = {'id': id}
try:
get_action('follow_group')(context, data_dict)
h.flash_success(_("You are now following {0}").format(id))
except ValidationError as e:
error_message = (e.extra_msg or e.message or e.error_summary
or e.error_dict)
h.flash_error(error_message)
except NotAuthorized as e:
h.flash_error(e.extra_msg)
h.redirect_to(controller='group', action='read', id=id)

def unfollow(self, id):
'''Stop following this group.'''
context = {'model': model,
'session': model.Session,
'user': c.user or c.author}
data_dict = {'id': id}
try:
get_action('unfollow_group')(context, data_dict)
h.flash_success(_("You are no longer following {0}").format(id))
except ValidationError as e:
error_message = (e.extra_msg or e.message or e.error_summary
or e.error_dict)
h.flash_error(error_message)
except (NotFound, NotAuthorized) as e:
error_message = e.extra_msg or e.message
h.flash_error(error_message)
h.redirect_to(controller='group', action='read', id=id)

def followers(self, id=None):
context = self._get_group_dict(id)
c.followers = get_action('group_follower_list')(context,
{'id': c.group_dict['id']})
return render('group/followers.html')

def admins(self, id=None):
context = self._get_group_dict(id)
c.admins = self.authorizer.get_admins(context['group'])
return render('group/admins.html')

def about(self, id=None):
self._get_group_dict(id)
return render('group/about.html')

def _get_group_dict(self, id):
context = {'model': model, 'session': model.Session,
'user': c.user or c.author,
'for_view': True}
data_dict = {'id': id}
try:
c.group_dict = get_action('group_show')(context, data_dict)
c.admins = self.authorizer.get_admins(context['group'])
except NotFound:
abort(404, _('Group not found'))
except NotAuthorized:
abort(401, _('Unauthorized to read group %s') % id)
return context

def _render_edit_form(self, fs):
# errors arrive in c.error and fs.errors
c.fieldset = fs
Expand Down
16 changes: 12 additions & 4 deletions ckan/lib/activity_streams.py
Expand Up @@ -33,7 +33,10 @@ def get_snippet_tag(activity, detail):
return h.tag_link(detail['data']['tag'])

def get_snippet_group(activity, detail):
return h.group_link(activity['data']['group'])
link = h.group_link(activity['data']['group'])
return literal('''<span data-module="popover-context" data-module-type="group" data-module-id="%s">%s</span>'''
% (activity['object_id'], link)
)

def get_snippet_extra(activity, detail):
return '"%s"' % detail['data']['package_extra']['key']
Expand Down Expand Up @@ -111,6 +114,9 @@ def activity_stream_string_follow_dataset():
def activity_stream_string_follow_user():
return _("{actor} started following {user}")

def activity_stream_string_follow_group():
return _("{actor} started following {group}")

def activity_stream_string_new_related_item():
return _("{actor} created the link to related {related_type} {related_item}")

Expand Down Expand Up @@ -149,22 +155,23 @@ def activity_stream_string_new_related_item():
'deleted related item': activity_stream_string_deleted_related_item,
'follow dataset': activity_stream_string_follow_dataset,
'follow user': activity_stream_string_follow_user,
'follow group': activity_stream_string_follow_group,
'new related item': activity_stream_string_new_related_item,
}

# A dictionary mapping activity types to the icons associated to them
activity_stream_string_icons = {
'added tag': 'tag',
'changed group': 'users',
'changed group': 'group',
'changed package': 'sitemap',
'changed package_extra': 'edit',
'changed resource': 'file',
'changed user': 'user',
'deleted group': 'users',
'deleted group': 'group',
'deleted package': 'sitemap',
'deleted package_extra': 'edit',
'deleted resource': 'file',
'new group': 'users',
'new group': 'group',
'new package': 'sitemap',
'new package_extra': 'edit',
'new resource': 'file',
Expand All @@ -173,6 +180,7 @@ def activity_stream_string_new_related_item():
'deleted related item': 'picture',
'follow dataset': 'sitemap',
'follow user': 'user',
'follow group': 'group',
'new related item': 'picture',
}

Expand Down
3 changes: 3 additions & 0 deletions ckan/lib/dictization/model_dictize.py
Expand Up @@ -575,3 +575,6 @@ def user_following_user_dictize(follower, context):

def user_following_dataset_dictize(follower, context):
return d.table_dictize(follower, context)

def user_following_group_dictize(follower, context):
return d.table_dictize(follower, context)
13 changes: 2 additions & 11 deletions ckan/lib/dictization/model_save.py
Expand Up @@ -594,19 +594,10 @@ def tag_dict_save(tag_dict, context):
tag = d.table_dict_save(tag_dict, model.Tag, context)
return tag

def user_following_user_dict_save(data_dict, context):
def follower_dict_save(data_dict, context, FollowerClass):
model = context['model']
session = context['session']
follower_obj = model.UserFollowingUser(
follower_id=model.User.get(context['user']).id,
object_id=data_dict['id'])
session.add(follower_obj)
return follower_obj

def user_following_dataset_dict_save(data_dict, context):
model = context['model']
session = context['session']
follower_obj = model.UserFollowingDataset(
follower_obj = FollowerClass(
follower_id=model.User.get(context['user']).id,
object_id=data_dict['id'])
session.add(follower_obj)
Expand Down
4 changes: 2 additions & 2 deletions ckan/lib/helpers.py
Expand Up @@ -887,7 +887,7 @@ def tag_link(tag):

def group_link(group):
url = url_for(controller='group', action='read', id=group['name'])
return link_to(group['name'], url)
return link_to(group['title'], url)


def dump_json(obj, **kw):
Expand Down Expand Up @@ -963,7 +963,7 @@ def process_names(items):
return items

# these are the types of objects that can be followed
_follow_objects = ['dataset', 'user']
_follow_objects = ['dataset', 'user', 'group']


def follow_button(obj_type, obj_id):
Expand Down
79 changes: 75 additions & 4 deletions ckan/logic/action/create.py
Expand Up @@ -924,8 +924,8 @@ def follow_user(context, data_dict):
'You are already following {0}').format(data_dict['id'])
raise ValidationError({'message': message}, error_summary=message)

follower = model_save.user_following_user_dict_save(validated_data_dict,
context)
follower = model_save.follower_dict_save(validated_data_dict, context,
model.UserFollowingUser)

activity_dict = {
'user_id': userobj.id,
Expand Down Expand Up @@ -995,8 +995,8 @@ def follow_dataset(context, data_dict):
'You are already following {0}').format(data_dict['id'])
raise ValidationError({'message': message}, error_summary=message)

follower = model_save.user_following_dataset_dict_save(
validated_data_dict, context)
follower = model_save.follower_dict_save(validated_data_dict, context,
model.UserFollowingDataset)

activity_dict = {
'user_id': userobj.id,
Expand All @@ -1023,3 +1023,74 @@ def follow_dataset(context, data_dict):
follower=follower.follower_id, object=follower.object_id))

return model_dictize.user_following_dataset_dictize(follower, context)


def follow_group(context, data_dict):
'''Start following a group.
You must provide your API key in the Authorization header.
:param id: the id or name of the group to follow, e.g. ``'roger'``
:type id: string
:returns: a representation of the 'follower' relationship between yourself
and the group
:rtype: dictionary
'''
if 'user' not in context:
raise logic.NotAuthorized(
_("You must be logged in to follow a group."))

model = context['model']
session = context['session']

userobj = model.User.get(context['user'])
if not userobj:
raise logic.NotAuthorized(
_("You must be logged in to follow a group."))

schema = context.get('schema',
ckan.logic.schema.default_follow_group_schema())

validated_data_dict, errors = _validate(data_dict, schema, context)

if errors:
model.Session.rollback()
raise ValidationError(errors)

# Don't let a user follow a group she is already following.
if model.UserFollowingGroup.is_following(userobj.id,
validated_data_dict['id']):
message = _(
'You are already following {0}').format(data_dict['id'])
raise ValidationError({'message': message}, error_summary=message)

follower = model_save.follower_dict_save(validated_data_dict, context,
model.UserFollowingGroup)

activity_dict = {
'user_id': userobj.id,
'object_id': validated_data_dict['id'],
'activity_type': 'follow group',
}
activity_dict['data'] = {
'group': ckan.lib.dictization.table_dictize(
model.Group.get(validated_data_dict['id']), context),
}
activity_create_context = {
'model': model,
'user': userobj,
'defer_commit': True,
'session': session
}
logic.get_action('activity_create')(activity_create_context,
activity_dict, ignore_auth=True)

if not context.get('defer_commit'):
model.repo.commit()

log.debug(u'User {follower} started following group {object}'.format(
follower=follower.follower_id, object=follower.object_id))

return model_dictize.user_following_group_dictize(follower, context)
19 changes: 15 additions & 4 deletions ckan/logic/action/delete.py
Expand Up @@ -312,10 +312,6 @@ def package_relationship_delete_rest(context, data_dict):
package_relationship_delete(context, data_dict)

def _unfollow(context, data_dict, schema, FollowerClass):
validated_data_dict, errors = validate(data_dict, schema, context)
if errors:
raise ValidationError(errors)

model = context['model']

if not context.has_key('user'):
Expand All @@ -327,6 +323,9 @@ def _unfollow(context, data_dict, schema, FollowerClass):
_("You must be logged in to unfollow something."))
follower_id = userobj.id

validated_data_dict, errors = validate(data_dict, schema, context)
if errors:
raise ValidationError(errors)
object_id = validated_data_dict.get('id')

follower_obj = FollowerClass.get(follower_id, object_id)
Expand Down Expand Up @@ -359,3 +358,15 @@ def unfollow_dataset(context, data_dict):
ckan.logic.schema.default_follow_dataset_schema())
_unfollow(context, data_dict, schema,
context['model'].UserFollowingDataset)

def unfollow_group(context, data_dict):
'''Stop following a group.
:param id: the id or name of the group to stop following
:type id: string
'''
schema = context.get('schema',
ckan.logic.schema.default_follow_group_schema())
_unfollow(context, data_dict, schema,
context['model'].UserFollowingGroup)

0 comments on commit f6026f9

Please sign in to comment.