Skip to content

Commit

Permalink
[#1494][#1496] Save pkg and res in activity tables
Browse files Browse the repository at this point in the history
When recording an activity or activity detail for a new or changed
package or resource, save a copy of the package or resource (dictized
and dumped as json) to the 'data' column of the activity or
activity_detail table.

In the activity stream templates get package and resource titles etc.
from this data, instead of querying the controller functions for them.

This means that if a package or resource name changes, old activity
events will still show the name from the time of the activity, if a
package or resource gets deleted old activity events will still have
access to the data, etc.

It also reduces extra database accesses when rendering activity streams.

And it means that this data about the package or resource that the
activity relates to is available in the json from the api call.
  • Loading branch information
Sean Hammond committed Jan 6, 2012
1 parent 3f50cce commit c3627bb
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 70 deletions.
45 changes: 4 additions & 41 deletions ckan/logic/action/get.py
Expand Up @@ -892,49 +892,16 @@ def activity_detail_list(context, data_dict):
return activity_detail_list_dictize(activity_detail_objects, context)

def render_new_package_activity(context, activity):

# FIXME: Get package from 'data' key of activity dict, not from model.
package = package_show(context=context,
data_dict={'id': activity['object_id']})

return render('activity_streams/new_package.html',
extra_vars = {'activity':activity, 'package':package})
extra_vars = {'activity': activity})

def render_new_resource_activity(context, activity, detail):

# FIXME: Get package from 'data' key of activity dict, not from model.
package = package_show(context=context,
data_dict={'id': activity['object_id']})

# FIXME: Get resource from 'data' key of detail dict, not from model, then
# won't have to skip resources that have since been deleted from model.
try:
resource = resource_show(context=context,
data_dict={'id': detail['object_id']})
except NotFound:
return ''

return render('activity_streams/new_resource.html',
extra_vars = {'activity': activity, 'package': package, 'resource':
resource})
extra_vars = {'activity': activity, 'detail': detail})

def render_changed_resource_activity(context, activity, detail):

# FIXME: Get package from 'data' key of activity dict, not from model.
package = package_show(context=context,
data_dict={'id': activity['object_id']})

# FIXME: Get resource from 'data' key of detail dict, not from model, then
# won't have to skip resources that have since been deleted from model.
try:
resource = resource_show(context=context,
data_dict={'id': detail['object_id']})
except NotFound:
return ''

return render('activity_streams/changed_resource.html',
extra_vars = {'activity': activity, 'package': package, 'resource':
resource})
extra_vars = {'activity': activity, 'detail': detail})

def render_changed_package_activity(context, activity):
details = activity_detail_list(context=context,
Expand All @@ -954,12 +921,8 @@ def render_changed_package_activity(context, activity):
renderer = activity_detail_renderers[object_type][activity_type]
return renderer(context, activity, detail)

# FIXME: Get package from 'data' key of activity dict, not from model.
package = package_show(context=context,
data_dict={'id': activity['object_id']})

return render('activity_streams/changed_package.html',
extra_vars = {'activity':activity, 'package':package})
extra_vars = {'activity': activity})

# Global dictionary mapping activity types to functions that render activity
# dicts to HTML snippets for including in HTML pages.
Expand Down
20 changes: 14 additions & 6 deletions ckan/model/activity.py
Expand Up @@ -4,6 +4,7 @@

from meta import *
from types import make_uuid
from types import JsonDictType
from core import *
from package import *

Expand All @@ -19,7 +20,7 @@
Column('object_id', types.UnicodeText),
Column('revision_id', types.UnicodeText),
Column('activity_type', types.UnicodeText),
Column('data', types.UnicodeText),
Column('data', JsonDictType),
)

activity_detail_table = Table(
Expand All @@ -29,31 +30,38 @@
Column('object_id', types.UnicodeText),
Column('object_type', types.UnicodeText),
Column('activity_type', types.UnicodeText),
Column('data', types.UnicodeText),
Column('data', JsonDictType),
)

class Activity(DomainObject):

def __init__(self, user_id, object_id, revision_id, activity_type, data):
def __init__(self, user_id, object_id, revision_id, activity_type,
data=None):
self.id = make_uuid()
self.timestamp = datetime.datetime.now()
self.user_id = user_id
self.object_id = object_id
self.revision_id = revision_id
self.activity_type = activity_type
self.data = data
if data is None:
self.data = {}
else:
self.data = data

mapper(Activity, activity_table)

class ActivityDetail(DomainObject):

def __init__(self, activity_id, object_id, object_type, activity_type,
data):
data=None):
self.activity_id = activity_id
self.object_id = object_id
self.object_type = object_type
self.activity_type = activity_type
self.data = data
if data is None:
self.data = {}
else:
self.data = data

mapper(ActivityDetail, activity_detail_table, properties = {
'activity':orm.relation ( Activity, backref=orm.backref('activity_detail'))
Expand Down
13 changes: 9 additions & 4 deletions ckan/model/package.py
Expand Up @@ -543,17 +543,22 @@ def get_fields(core_only=False, fields_to_ignore=None):
return fields

def activity_stream_item(self, activity_type, revision, user_id):
import ckan.model as model
from ckan.lib.dictization.model_dictize import package_dictize
assert activity_type in ("new", "changed", "deleted"), \
str(activity_type)
if activity_type == "new":
return Activity(user_id, self.id, revision.id, "new package", None)
return Activity(user_id, self.id, revision.id, "new package",
{'package': package_dictize(self, context={'model':model})})
elif activity_type == "changed":
return Activity(user_id, self.id, revision.id, "changed package",
None)
{'package': package_dictize(self, context={'model':model})})
elif activity_type == "deleted":
return Activity(user_id, self.id, revision.id, "deleted package",
None)
{'package': package_dictize(self, context={'model':model})})

def activity_stream_detail(self, activity_id, activity_type):
import ckan.model as model
from ckan.lib.dictization.model_dictize import package_dictize
return ActivityDetail(activity_id, self.id, u"Package", activity_type,
data=None)
{'package': package_dictize(self, context={'model':model})})
4 changes: 3 additions & 1 deletion ckan/model/resource.py
Expand Up @@ -141,8 +141,10 @@ def related_packages(self):
return [self.resource_group.package]

def activity_stream_detail(self, activity_id, activity_type):
import ckan.model as model
from ckan.lib.dictization.model_dictize import resource_dictize
return ActivityDetail(activity_id, self.id, u"Resource", activity_type,
None)
{'resource': resource_dictize(self, context={'model':model})})

class ResourceGroup(vdm.sqlalchemy.RevisionedObjectMixin,
vdm.sqlalchemy.StatefulObjectMixin,
Expand Down
8 changes: 4 additions & 4 deletions ckan/templates/activity_streams/changed_package.html
Expand Up @@ -8,14 +8,14 @@
<xi:include href="../_util.html" />
<div>
<div style="font-weight:bold;">
${h.linked_user(activity['user_id'])}
${h.linked_user(activity.user_id)}
<span style="background:yellow;">updated</span>
the dataset
${package_summary(package)} <br/>
${h.render_datetime(activity['timestamp'], '%B %d %Y')}
${package_summary(activity.data.package)} <br/>
${h.render_datetime(activity.timestamp, '%B %d %Y')}
</div>
<div style="color:#999;">
${h.markdown_extract(package.notes)}
${h.markdown_extract(activity.data.package.notes)}
</div>
</div>
</html>
10 changes: 5 additions & 5 deletions ckan/templates/activity_streams/changed_resource.html
Expand Up @@ -8,14 +8,14 @@
<xi:include href="../_util.html" />
<div>
<div style="font-weight:bold;">
${h.linked_user(activity['user_id'])}
${h.linked_user(activity.user_id)}
<span style="background:yellow;">updated</span>
the resource ${resource_summary(package, resource)}
in the dataset ${package_summary(package)}<br/>
${h.render_datetime(activity['timestamp'], '%B %d %Y')}
the resource ${resource_summary(activity.data.package, detail.data.resource)}
in the dataset ${package_summary(activity.data.package)}<br/>
${h.render_datetime(activity.timestamp, '%B %d %Y')}
</div>
<div style="color:#999;">
${h.markdown_extract(package.notes)}
${h.markdown_extract(activity.data.package.notes)}
</div>
</div>
</html>
8 changes: 4 additions & 4 deletions ckan/templates/activity_streams/new_package.html
Expand Up @@ -8,14 +8,14 @@
<xi:include href="../_util.html" />
<div>
<div style="font-weight:bold;">
${h.linked_user(activity['user_id'])}
${h.linked_user(activity.user_id)}
<span style="background:yellow;">created</span>
the dataset
${package_summary(package)} <br/>
${h.render_datetime(activity['timestamp'], '%B %d %Y')}
${package_summary(activity.data.package)} <br/>
${h.render_datetime(activity.timestamp, '%B %d %Y')}
</div>
<div style="color:#999;">
${h.markdown_extract(package.notes)}
${h.markdown_extract(activity.data.package.notes)}
</div>
</div>
</html>
10 changes: 5 additions & 5 deletions ckan/templates/activity_streams/new_resource.html
Expand Up @@ -8,14 +8,14 @@
<xi:include href="../_util.html" />
<div>
<div style="font-weight:bold;">
${h.linked_user(activity['user_id'])}
${h.linked_user(activity.user_id)}
<span style="background:yellow;">added</span>
the resource ${resource_summary(package, resource)}
to the dataset ${package_summary(package)}<br/>
${h.render_datetime(activity['timestamp'], '%B %d %Y')}
the resource ${resource_summary(activity.data.package, detail.data.resource)}
to the dataset ${package_summary(activity.data.package)}<br/>
${h.render_datetime(activity.timestamp, '%B %d %Y')}
</div>
<div style="color:#999;">
${h.markdown_extract(package.notes)}
${h.markdown_extract(activity.data.package.notes)}
</div>
</div>
</html>

0 comments on commit c3627bb

Please sign in to comment.