Start of unification of comment and activity streams.
This commit is contained in:
@@ -88,9 +88,10 @@ class AttractExtension(PillarExtension):
|
|||||||
def setup_app(self, app):
|
def setup_app(self, app):
|
||||||
"""Connects Blinker signals and sets up other app-dependent stuff in submodules."""
|
"""Connects Blinker signals and sets up other app-dependent stuff in submodules."""
|
||||||
|
|
||||||
from . import subversion, tasks, eve_hooks, shots
|
from . import comments, subversion, tasks, eve_hooks, shots
|
||||||
|
|
||||||
subversion.task_logged.connect(self.task_manager.api_task_logged_in_svn)
|
subversion.task_logged.connect(self.task_manager.api_task_logged_in_svn)
|
||||||
|
comments.setup_app(app)
|
||||||
tasks.setup_app(app)
|
tasks.setup_app(app)
|
||||||
shots.setup_app(app)
|
shots.setup_app(app)
|
||||||
eve_hooks.setup_app(app)
|
eve_hooks.setup_app(app)
|
||||||
@@ -165,14 +166,21 @@ class AttractExtension(PillarExtension):
|
|||||||
def activities_for_node(self, node_id, max_results=20, page=1):
|
def activities_for_node(self, node_id, max_results=20, page=1):
|
||||||
"""Returns a page of activities for the given task or shot.
|
"""Returns a page of activities for the given task or shot.
|
||||||
|
|
||||||
|
Activities that are either on this node or have this node as context
|
||||||
|
are returned.
|
||||||
|
|
||||||
:returns: {'_items': [task, task, ...], '_meta': {Eve metadata}}
|
:returns: {'_items': [task, task, ...], '_meta': {Eve metadata}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
api = pillar_api()
|
api = pillar_api()
|
||||||
activities = pillarsdk.Activity.all({
|
activities = pillarsdk.Activity.all({
|
||||||
'where': {
|
'where': {
|
||||||
'object_type': 'node',
|
'$or': [
|
||||||
'object': node_id,
|
{'object_type': 'node',
|
||||||
|
'object': node_id},
|
||||||
|
{'context_object_type': 'node',
|
||||||
|
'context_object': node_id},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'sort': [('_created', -1)],
|
'sort': [('_created', -1)],
|
||||||
'max_results': max_results,
|
'max_results': max_results,
|
||||||
|
5
attract/comments/__init__.py
Normal file
5
attract/comments/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
def setup_app(app):
|
||||||
|
from . import eve_hooks
|
||||||
|
|
||||||
|
eve_hooks.setup_app(app)
|
39
attract/comments/eve_hooks.py
Normal file
39
attract/comments/eve_hooks.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
from pillar.api.nodes import only_for_node_type_decorator
|
||||||
|
import pillar.api.activities
|
||||||
|
import pillar.api.utils.authentication
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
comment_nodes_only = only_for_node_type_decorator('comment')
|
||||||
|
|
||||||
|
|
||||||
|
@comment_nodes_only
|
||||||
|
def activity_after_creating_node(comment):
|
||||||
|
comment_id = comment['_id']
|
||||||
|
parent_id = comment.get('parent', None)
|
||||||
|
|
||||||
|
if not parent_id:
|
||||||
|
log.warning('Comment %s created without parent.' % comment_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.debug('Recording creation of comment as activity on node %s', parent_id)
|
||||||
|
|
||||||
|
pillar.api.activities.register_activity(
|
||||||
|
pillar.api.utils.authentication.current_user_id(),
|
||||||
|
'commented',
|
||||||
|
'node', comment_id,
|
||||||
|
'node', parent_id,
|
||||||
|
project_id=comment.get('project', None),
|
||||||
|
node_type=comment['node_type'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def activity_after_creating_nodes(nodes):
|
||||||
|
for node in nodes:
|
||||||
|
activity_after_creating_node(node)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_app(app):
|
||||||
|
app.on_inserted_nodes += activity_after_creating_nodes
|
@@ -48,12 +48,17 @@ def activity_after_replacing_shot(shot, original):
|
|||||||
human_key = human_readable_properties[key]
|
human_key = human_readable_properties[key]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
human_key = pillar.web.jinja.format_undertitle(key.rsplit('.', 1)[-1])
|
human_key = pillar.web.jinja.format_undertitle(key.rsplit('.', 1)[-1])
|
||||||
|
descr = None
|
||||||
|
|
||||||
if key == 'properties.status':
|
# Some key- and value-specific overrides
|
||||||
|
if val_shot is pillar.api.utils.DoesNotExist:
|
||||||
|
descr = 'removed "%s" from shot "%s"' % (human_key, shot['name'])
|
||||||
|
elif key == 'properties.status':
|
||||||
val_shot = pillar.web.jinja.format_undertitle(val_shot)
|
val_shot = pillar.web.jinja.format_undertitle(val_shot)
|
||||||
elif isinstance(val_shot, basestring) and len(val_shot) > 80:
|
elif isinstance(val_shot, basestring) and len(val_shot) > 80:
|
||||||
val_shot = val_shot[:80] + u'…'
|
val_shot = val_shot[:80] + u'…'
|
||||||
|
|
||||||
|
if descr is None:
|
||||||
descr = 'changed "%s" to "%s" in shot "%s"' %\
|
descr = 'changed "%s" to "%s" in shot "%s"' %\
|
||||||
(human_key, val_shot, shot['name'])
|
(human_key, val_shot, shot['name'])
|
||||||
else:
|
else:
|
||||||
|
@@ -139,8 +139,10 @@ def activity_after_replacing_task(task, original):
|
|||||||
human_key = pillar.web.jinja.format_undertitle(key.rsplit('.', 1)[-1])
|
human_key = pillar.web.jinja.format_undertitle(key.rsplit('.', 1)[-1])
|
||||||
descr = None
|
descr = None
|
||||||
|
|
||||||
# Some key-specific overrides
|
# Some key- and value-specific overrides
|
||||||
if key == 'properties.status':
|
if val_task is pillar.api.utils.DoesNotExist:
|
||||||
|
descr = 'removed "%s" from shot "%s"' % (human_key, task['name'])
|
||||||
|
elif key == 'properties.status':
|
||||||
val_task = pillar.web.jinja.format_undertitle(val_task)
|
val_task = pillar.web.jinja.format_undertitle(val_task)
|
||||||
elif key == 'properties.assigned_to.users':
|
elif key == 'properties.assigned_to.users':
|
||||||
human_key = 'assigned users'
|
human_key = 'assigned users'
|
||||||
@@ -148,6 +150,7 @@ def activity_after_replacing_task(task, original):
|
|||||||
descr = 'assigned task "%s" to %s' % (task['name'], val_task)
|
descr = 'assigned task "%s" to %s' % (task['name'], val_task)
|
||||||
elif isinstance(val_task, basestring) and len(val_task) > 80:
|
elif isinstance(val_task, basestring) and len(val_task) > 80:
|
||||||
val_task = val_task[:80] + u'…'
|
val_task = val_task[:80] + u'…'
|
||||||
|
|
||||||
if descr is None:
|
if descr is None:
|
||||||
descr = 'changed %s to "%s" in task "%s"' % (human_key, val_task, task['name'])
|
descr = 'changed %s to "%s" in task "%s"' % (human_key, val_task, task['name'])
|
||||||
else:
|
else:
|
||||||
|
@@ -116,7 +116,7 @@ script.
|
|||||||
});
|
});
|
||||||
|
|
||||||
loadActivities("{{ url_for('.activities', project_url=project.url, shot_id=shot['_id']) }}"); // from 10_tasks.js
|
loadActivities("{{ url_for('.activities', project_url=project.url, shot_id=shot['_id']) }}"); // from 10_tasks.js
|
||||||
loadComments("{{ url_for('nodes.comments_for_node', node_id=shot['_id']) }}");
|
loadComments("{{ url_for('nodes.commentform_for_node', node_id=shot['_id']) }}");
|
||||||
|
|
||||||
$('.js-help').openModalUrl('Help', "{{ url_for('attract.help', project_url=project.url) }}");
|
$('.js-help').openModalUrl('Help', "{{ url_for('attract.help', project_url=project.url) }}");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user