Skip to content

Commit

Permalink
Merge branch 'master' into 2939-orgs
Browse files Browse the repository at this point in the history
Conflicts:
	ckan/lib/dictization/model_dictize.py
	ckan/model/group.py
	ckan/tests/functional/api/test_follow.py
	ckan/tests/functional/test_group.py
  • Loading branch information
tobes committed Nov 29, 2012
2 parents 07b4fa5 + 740a0d8 commit 0429cb9
Show file tree
Hide file tree
Showing 25 changed files with 828 additions and 915 deletions.
3 changes: 2 additions & 1 deletion ckan/config/routing.py
Expand Up @@ -188,6 +188,7 @@ def make_map():
'history',
'read_ajax',
'history_ajax',
'activity',
'followers',
'follow',
'unfollow',
Expand Down Expand Up @@ -279,7 +280,7 @@ def make_map():
# Note: openid users have slashes in their ids, so need the wildcard
# in the route.
m.connect('/user/activity/{id}', action='activity')
m.connect('/user/dashboard', action='dashboard')
m.connect('/dashboard', action='dashboard')
m.connect('/user/follow/{id}', action='follow')
m.connect('/user/unfollow/{id}', action='unfollow')
m.connect('/user/followers/{id:.*}', action='followers')
Expand Down
2 changes: 1 addition & 1 deletion ckan/controllers/group.py
Expand Up @@ -387,7 +387,7 @@ def _force_reindex(self, grp):
appearing on the read page for the group (as they're connected via
the group name)'''
group = model.Group.get(grp['name'])
for dataset in group.active_packages().all():
for dataset in group.packages():
search.rebuild(dataset.name)

def _save_edit(self, id, context):
Expand Down
27 changes: 20 additions & 7 deletions ckan/controllers/package.py
Expand Up @@ -317,13 +317,6 @@ def read(self, id, format='html'):
c.current_package_id = c.pkg.id
c.related_count = c.pkg.related_count

# Add the package's activity stream (already rendered to HTML) to the
# template context for the package/read.html template to retrieve
# later.
c.package_activity_stream = \
get_action('package_activity_list_html')(
context, {'id': c.current_package_id})

PackageSaver().render_package(c.pkg_dict, context)

template = self._read_template(package_type)
Expand Down Expand Up @@ -1239,6 +1232,26 @@ def followers(self, id=None):

return render('package/followers.html')

def activity(self, id):
'''Render this package's public activity stream page.'''

context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'for_view': True}
data_dict = {'id': id}
try:
c.pkg_dict = get_action('package_show')(context, data_dict)
c.pkg = context['package']
c.package_activity_stream = get_action(
'package_activity_list_html')(context,
{'id': c.pkg_dict['id']})
c.related_count = c.pkg.related_count
except NotFound:
abort(404, _('Dataset not found'))
except NotAuthorized:
abort(401, _('Unauthorized to read dataset %s') % id)

return render('package/activity.html')

def resource_embedded_dataviewer(self, id, resource_id,
width=500, height=500):
"""
Expand Down
3 changes: 1 addition & 2 deletions ckan/lib/dictization/model_dictize.py
Expand Up @@ -32,8 +32,7 @@ def group_list_dictize(obj_list, context,
group_dict['display_name'] = obj.display_name

group_dict['packages'] = \
len(obj.active_packages(with_private=with_private,
context=context).all())
len(obj.packages(with_private=with_private, context=context))

if context.get('for_view'):
if group_dict['is_organization']:
Expand Down
53 changes: 9 additions & 44 deletions ckan/logic/action/get.py
Expand Up @@ -872,34 +872,22 @@ def group_package_show(context, data_dict):
:rtype: list of dictionaries
'''
model = context["model"]
user = context["user"]
id = _get_or_bust(data_dict, 'id')
limit = data_dict.get("limit")
model = context['model']
group_id = _get_or_bust(data_dict, 'id')

group = model.Group.get(id)
# FIXME: What if limit is not an int? Schema and validation needed.
limit = data_dict.get('limit')

group = model.Group.get(group_id)
context['group'] = group
if group is None:
raise NotFound

_check_access('group_show', context, data_dict)

query = model.Session.query(model.PackageRevision)\
.filter(model.PackageRevision.state=='active')\
.filter(model.PackageRevision.current==True)\
.join(model.Member, model.Member.table_id==model.PackageRevision.id)\
.join(model.Group, model.Group.id==model.Member.group_id)\
.filter_by(id=group.id)\
.order_by(model.PackageRevision.name)

if limit:
query = query.limit(limit)

if context.get('return_query'):
return query

result = []
for pkg_rev in query.all():
for pkg_rev in group.packages(limit=limit,
return_query=context.get('return_query')):
result.append(model_dictize.package_dictize(pkg_rev, context))

return result
Expand Down Expand Up @@ -1902,30 +1890,7 @@ def group_activity_list(context, data_dict):
group_show = logic.get_action('group_show')
group_id = group_show(context, {'id': group_id})['id']

# FIXME: The SQLAlchemy below should be moved into ckan/model/activity.py
# (to encapsulate SQLALchemy in the model and avoid using it from the
# logic) but it can't be because it requires the list of dataset_ids which
# comes from logic.group_package_show() (and I don't want to access the
# logic from the model). Need to change it to get the dataset_ids from the
# model instead. There seems to be multiple methods for getting a group's
# datasets, some in the logic and some in the model.

# Get a list of the IDs of the group's datasets.
group_package_show = logic.get_action('group_package_show')
datasets = group_package_show(context, {'id': group_id})
dataset_ids = [dataset['id'] for dataset in datasets]

# Get the group's activities.
query = model.Session.query(model.Activity)
if dataset_ids:
query = query.filter(_or_(model.Activity.object_id == group_id,
model.Activity.object_id.in_(dataset_ids)))
else:
query = query.filter(model.Activity.object_id == group_id)
query = query.order_by(_desc(model.Activity.timestamp))
query = query.limit(15)
activity_objects = query.all()

activity_objects = model.activity.group_activity_list(group_id)
return model_dictize.activity_list_dictize(activity_objects, context)

def organization_activity_list(context, data_dict):
Expand Down
98 changes: 92 additions & 6 deletions ckan/model/activity.py
@@ -1,6 +1,6 @@
import datetime

from sqlalchemy import orm, types, Column, Table, ForeignKey, desc
from sqlalchemy import orm, types, Column, Table, ForeignKey, desc, or_

import meta
import types as _types
Expand Down Expand Up @@ -69,6 +69,7 @@ def __init__(self, activity_id, object_id, object_type, activity_type,


def _most_recent_activities(q, limit):
'''Return the 'limit' most recent activites from activity query 'q'.'''
import ckan.model as model
q = q.order_by(desc(model.Activity.timestamp))
if limit:
Expand All @@ -77,30 +78,33 @@ def _most_recent_activities(q, limit):


def _activities_from_user_query(user_id):
'''Return an SQLAlchemy query for all activities from user_id.'''
import ckan.model as model
q = model.Session.query(model.Activity)
q = q.filter(model.Activity.user_id == user_id)
return q


def _activities_about_user_query(user_id):
'''Return an SQLAlchemy query for all activities about user_id.'''
import ckan.model as model
q = model.Session.query(model.Activity)
q = q.filter(model.Activity.object_id == user_id)
return q


def _user_activity_query(user_id):
'''Return an SQLAlchemy query for all activities from or about user_id.'''
q = _activities_from_user_query(user_id)
q = q.union(_activities_about_user_query(user_id))
return q


def user_activity_list(user_id, limit=15):
'''Return the given user's public activity stream.
'''Return user_id's public activity stream.
Returns all activities from or about the given user, i.e. where the given
user is the subject or object of the activity, e.g.:
Return a list of all activities from or about the given user, i.e. where
the given user is the subject or object of the activity, e.g.:
"{USER} created the dataset {DATASET}"
"{OTHER_USER} started following {USER}"
Expand All @@ -112,6 +116,9 @@ def user_activity_list(user_id, limit=15):


def _package_activity_query(package_id):
'''Return an SQLAlchemy query for all activities about package_id.
'''
import ckan.model as model
q = model.Session.query(model.Activity)
q = q.filter_by(object_id=package_id)
Expand All @@ -133,7 +140,48 @@ def package_activity_list(package_id, limit=15):
return _most_recent_activities(q, limit)


def _group_activity_query(group_id, limit=15):
'''Return an SQLAlchemy query for all activities about group_id.
Returns a query for all activities whose object is either the group itself
or one of the group's datasets.
'''
import ckan.model as model

group = model.Group.get(group_id)
if not group:
# Return a query with no results.
return model.Session.query(model.Activity).filter("0=1")

dataset_ids = [dataset.id for dataset in group.packages()]

q = model.Session.query(model.Activity)
if dataset_ids:
q = q.filter(or_(model.Activity.object_id == group_id,
model.Activity.object_id.in_(dataset_ids)))
else:
q = q.filter(model.Activity.object_id == group_id)
return q


def group_activity_list(group_id, limit=15):
'''Return the given group's public activity stream.
Returns all activities where the given group or one of its datasets is the
object of the activity, e.g.:
"{USER} updated the group {GROUP}"
"{USER} updated the dataset {DATASET}"
etc.
'''
q = _group_activity_query(group_id)
return _most_recent_activities(q, limit)


def _activites_from_users_followed_by_user_query(user_id):
'''Return a query for all activities from users that user_id follows.'''
import ckan.model as model
q = model.Session.query(model.Activity)
q = q.join(model.UserFollowingUser,
Expand All @@ -143,6 +191,7 @@ def _activites_from_users_followed_by_user_query(user_id):


def _activities_from_datasets_followed_by_user_query(user_id):
'''Return a query for all activities from datasets that user_id follows.'''
import ckan.model as model
q = model.Session.query(model.Activity)
q = q.join(model.UserFollowingDataset,
Expand All @@ -151,9 +200,33 @@ def _activities_from_datasets_followed_by_user_query(user_id):
return q


def _activities_from_groups_followed_by_user_query(user_id):
'''Return a query for all activities about groups the given user follows.
Return a query for all activities about the groups the given user follows,
or about any of the group's datasets. This is the union of
_group_activity_query(group_id) for each of the groups the user follows.
'''
import ckan.model as model

# Get a list of the group's that the user is following.
follower_objects = model.UserFollowingGroup.followee_list(user_id)
if not follower_objects:
# Return a query with no results.
return model.Session.query(model.Activity).filter("0=1")

q = _group_activity_query(follower_objects[0].object_id)
q = q.union_all(*[_group_activity_query(follower.object_id)
for follower in follower_objects[1:]])
return q


def _activities_from_everything_followed_by_user_query(user_id):
'''Return a query for all activities from everything user_id follows.'''
q = _activites_from_users_followed_by_user_query(user_id)
q = q.union(_activities_from_datasets_followed_by_user_query(user_id))
q = q.union(_activities_from_groups_followed_by_user_query(user_id))
return q


Expand All @@ -169,6 +242,7 @@ def activities_from_everything_followed_by_user(user_id, limit=15):


def _dashboard_activity_query(user_id):
'''Return an SQLAlchemy query for user_id's dashboard activity stream.'''
q = _user_activity_query(user_id)
q = q.union(_activities_from_everything_followed_by_user_query(user_id))
return q
Expand All @@ -188,13 +262,25 @@ def dashboard_activity_list(user_id, limit=15):
return _most_recent_activities(q, limit)


def _recently_changed_packages_activity_query():
def _changed_packages_activity_query():
'''Return an SQLAlchemyu query for all changed package activities.
Return a query for all activities with activity_type '*package', e.g.
'new_package', 'changed_package', 'deleted_package'.
'''
import ckan.model as model
q = model.Session.query(model.Activity)
q = q.filter(model.Activity.activity_type.endswith('package'))
return q


def recently_changed_packages_activity_list(limit=15):
q = _recently_changed_packages_activity_query()
'''Return the site-wide stream of recently changed package activities.
This activity stream includes recent 'new package', 'changed package' and
'deleted package' activities for the whole site.
'''
q = _changed_packages_activity_query()
return _most_recent_activities(q, limit)

0 comments on commit 0429cb9

Please sign in to comment.