Display activity stream on project page #2222
Web handler and template to show activity stream on project page Review ID: 358001
This commit is contained in:
parent
201c7a8649
commit
3e3f9a7536
|
@ -11,7 +11,7 @@ from trytond.pool import Pool
|
|||
from project import (
|
||||
WebSite, ProjectUsers, ProjectInvitation,
|
||||
ProjectWorkInvitation, TimesheetEmployeeDay, Project, Tag,
|
||||
TaskTags, ProjectHistory, ProjectWorkCommit, Activity,
|
||||
TaskTags, ProjectHistory, ProjectWorkCommit, Activity, TimesheetLine,
|
||||
)
|
||||
from company import Company, CompanyProjectAdmins, NereidUser
|
||||
|
||||
|
@ -34,5 +34,6 @@ def register():
|
|||
Company,
|
||||
CompanyProjectAdmins,
|
||||
NereidUser,
|
||||
TimesheetLine,
|
||||
module='nereid_project', type_='model',
|
||||
)
|
||||
|
|
62
project.py
62
project.py
|
@ -36,12 +36,14 @@ from trytond.pool import Pool, PoolMeta
|
|||
from trytond.transaction import Transaction
|
||||
from trytond.pyson import Eval
|
||||
from trytond.config import CONFIG
|
||||
from trytond.tools import get_smtp_server, datetime_strftime
|
||||
from trytond.tools import get_smtp_server
|
||||
from trytond.backend import TableHandler
|
||||
|
||||
__all__ = ['WebSite', 'ProjectUsers', 'ProjectInvitation',
|
||||
'TimesheetEmployeeDay', 'ProjectWorkInvitation', 'Project', 'Tag',
|
||||
'TaskTags', 'ProjectHistory', 'ProjectWorkCommit', 'Activity',]
|
||||
'TaskTags', 'ProjectHistory', 'ProjectWorkCommit', 'Activity',
|
||||
'TimesheetLine',
|
||||
]
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
|
||||
|
@ -385,11 +387,13 @@ class Project:
|
|||
}
|
||||
if self.type == 'project':
|
||||
rv['url'] = url_for(
|
||||
'project.work.render_project', active_id=self.id
|
||||
'project.work.render_project', project_id=self.id
|
||||
)
|
||||
else:
|
||||
# TODO: Convert self.parent to self.project
|
||||
rv['url'] = url_for(
|
||||
'project.work.render_task', active_id=self.id
|
||||
'project.work.render_task', project_id=self.parent.id,
|
||||
task_id=self.id,
|
||||
)
|
||||
return rv
|
||||
|
||||
|
@ -1995,6 +1999,26 @@ class Project:
|
|||
flash("The estimated hours have been changed for this task.")
|
||||
return redirect(request.referrer)
|
||||
|
||||
@login_required
|
||||
def stream(self):
|
||||
'''
|
||||
Return stream for a project.
|
||||
'''
|
||||
Activity = Pool().get('nereid.activity')
|
||||
|
||||
self.can_read(request.nereid_user)
|
||||
page = request.args.get('page', 1, int)
|
||||
|
||||
domain = [('project', '=', self.id)]
|
||||
activities = Pagination(Activity, domain, page, 20)
|
||||
items = filter(
|
||||
None, map(lambda activity: activity.serialize(), activities)
|
||||
)
|
||||
return jsonify({
|
||||
'totalItems': activities.count,
|
||||
'items': items,
|
||||
})
|
||||
|
||||
|
||||
class Tag(ModelSQL, ModelView):
|
||||
"Tags"
|
||||
|
@ -2185,15 +2209,19 @@ class ProjectHistory(ModelSQL, ModelView):
|
|||
'''
|
||||
Serialize the history and returns a dictionary.
|
||||
'''
|
||||
# TODO: Return changed value also. So that it is possible to handle all
|
||||
# history events separately.
|
||||
return {
|
||||
"url": url_for(
|
||||
'project.work.render_task_list', comment=self.comment.id
|
||||
'project.work.render_task', project_id=self.project.parent.id,
|
||||
task_id=self.project.id,
|
||||
),
|
||||
"objectType": self.__name__,
|
||||
"id": self.id,
|
||||
"displayName": self.display_name,
|
||||
"displayName": self.rec_name,
|
||||
}
|
||||
|
||||
|
||||
@classmethod
|
||||
def create_history_line(cls, project, changed_values):
|
||||
"""
|
||||
|
@ -2481,6 +2509,28 @@ def invitation_new_user_handler(nereid_user_id):
|
|||
})
|
||||
|
||||
|
||||
class TimesheetLine:
|
||||
'''
|
||||
Timesheet Lines
|
||||
'''
|
||||
__name__ = 'timesheet.line'
|
||||
|
||||
def _json(self):
|
||||
'''
|
||||
Serialize timesheet line and returns a dictionary.
|
||||
'''
|
||||
# Render url for timesheet line is task on which this time is marked
|
||||
return {
|
||||
"url": url_for(
|
||||
'project.work.render_task', project_id=self.work.parent.id,
|
||||
task_id=self.work.id,
|
||||
),
|
||||
"objectType": self.__name__,
|
||||
"id": self.id,
|
||||
"displayName": "%dh %dm" % (self.hours, (self.hours * 60) % 60),
|
||||
}
|
||||
|
||||
|
||||
class Activity:
|
||||
'''
|
||||
Nereid user activity
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -135,6 +135,7 @@
|
|||
<script src="{{ STATIC }}js/jquery.meow.js"></script>
|
||||
<script src="{{ STATIC }}js/chosen.jquery.min.js"></script>
|
||||
<script src="{{ STATIC }}js/fullcalendar.min.js"></script>
|
||||
<script src="{{ STATIC }}js/underscore.js"></script>
|
||||
<!--<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script> -->
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -183,7 +183,9 @@
|
|||
{% block main %}
|
||||
|
||||
{% if request.endpoint == 'project.work.render_project' %}
|
||||
<div class="row-fluid" id="project_timeline"></div>
|
||||
<div class="row-fluid" id="project_timeline">
|
||||
<!-- Put stream here -->
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span5"></div>
|
||||
<a class="btn btn-mini" id="more_project_timeline">{{ _('Show More') }}</a>
|
||||
|
@ -193,8 +195,45 @@
|
|||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script id="created_project" type="text/template">
|
||||
<div class="well well-small">
|
||||
<a href="<%= actor.url %>"><%= actor.displayName %></a> created new project <a href="<%= object.url %>"><%= object.displayName %></a>.
|
||||
</div>
|
||||
</script>
|
||||
<script id="created_tag" type="text/template">
|
||||
<div class="well well-small">
|
||||
<a href="<%= actor.url %>"><%= actor.displayName %></a> created new tag <a href="<%= object.url %>"><%= object.displayName %></a> for <a href="<%= target.url %>"><%= target.displayName %></a>.
|
||||
</div>
|
||||
</script>
|
||||
<script id="created_task" type="text/template">
|
||||
<div class="well well-small">
|
||||
<a href="<%= actor.url %>"><%= actor.displayName %></a> created new task <a href="<%= object.url %>"><%= object.displayName %></a> for <a href="<%= target.url %>"><%= target.displayName %></a>.
|
||||
</div>
|
||||
</script>
|
||||
<script id="reported_time" type="text/template">
|
||||
<div class="well well-small">
|
||||
<a href="<%= actor.url %>"><%= actor.displayName %></a> worked for <b><%= object.displayName %></b> on <a href="<%= target.url %>"><%= target.displayName %></a>.
|
||||
</div>
|
||||
</script>
|
||||
<script id="updated_task" type="text/template">
|
||||
<!--
|
||||
TODO: Updated_task can have multiple events like commented, changed assignee, changed constrain date etc
|
||||
Handle all of them.
|
||||
-->
|
||||
<div class="well well-small">
|
||||
<a href="<%= actor.url %>"><%= actor.displayName %></a> updated <a href="<%= target.url %>"><%= target.displayName %></a>.
|
||||
</div>
|
||||
</script>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
var page = 0;
|
||||
|
||||
var created_project_template = _.template($("script#created_project").html());
|
||||
var created_tag_template = _.template($("script#created_tag").html());
|
||||
var created_task_template = _.template($("script#created_task").html());
|
||||
var reported_time_template = _.template($("script#reported_time").html());
|
||||
var updated_task_template = _.template($("script#updated_task").html());
|
||||
|
||||
// Remove a tag
|
||||
$('.btn-remove-tag').click(function(){
|
||||
tag_id = $(this).attr('id')
|
||||
|
@ -206,6 +245,39 @@
|
|||
$("div#" + tag_id).hide();
|
||||
});
|
||||
});
|
||||
|
||||
$("#more_project_timeline").click(function(e){
|
||||
e.preventDefault();
|
||||
$.getJSON("{{ url_for('project.work.stream', active_id=project.id) }}?page=" + ++page)
|
||||
.done(function(response){
|
||||
if (!response.items.length) {
|
||||
$("#more_project_timeline").remove();
|
||||
return;
|
||||
}
|
||||
_.each(response.items, function(item){
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
switch(item.verb) {
|
||||
case "created_project":
|
||||
$("#project_timeline").append(created_project_template(item));
|
||||
break;
|
||||
case "created_tag":
|
||||
$("#project_timeline").append(created_tag_template(item));
|
||||
break;
|
||||
case "created_task":
|
||||
$("#project_timeline").append(created_task_template(item));
|
||||
break;
|
||||
case "reported_time":
|
||||
$("#project_timeline").append(reported_time_template(item));
|
||||
break;
|
||||
case "updated_task":
|
||||
$("#project_timeline").append(updated_task_template(item));
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}).click();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
9
urls.xml
9
urls.xml
|
@ -273,5 +273,14 @@
|
|||
<field name="sequence" eval="60" />
|
||||
<field name="url_map" ref="nereid.default_url_map" />
|
||||
</record>
|
||||
|
||||
<!-- Project Activities -->
|
||||
<record id="project_activity_stream" model="nereid.url_rule">
|
||||
<field name="rule">/<language>/project-<int:active_id>/stream</field>
|
||||
<field name="endpoint">project.work.stream</field>
|
||||
<field name="sequence" eval="50" />
|
||||
<field name="http_method_get" eval="True"/>
|
||||
<field name="url_map" ref="nereid.default_url_map" />
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
Loading…
Reference in New Issue