timeline items header

stable
Juanfran 2015-04-14 12:25:20 +02:00
parent c439ca7e3f
commit 8cc04a7f58
9 changed files with 303 additions and 57 deletions

View File

@ -0,0 +1,13 @@
CompileHtmlDirective = ($compile) ->
link = (scope, element, attrs) ->
scope.$watch attrs.tgCompileHtml, (newValue, oldValue) ->
element.html(newValue)
$compile(element.contents())(scope)
return {
link: link
}
CompileHtmlDirective.$inject = ["$compile"]
angular.module("taigaCommon").directive("tgCompileHtml", CompileHtmlDirective)

View File

@ -30,16 +30,33 @@ class ProfileTimelineController extends mixOf(taiga.Controller, taiga.PageMixin,
"$tgAuth"
]
valid_fields: ['status', 'subject', 'description', 'assigned_to', 'points', 'severity', 'priority', 'type', 'attachments', 'milestone', 'is_blocked', 'is_iocaine', 'content_diff', 'name', 'estimated_finish', 'estimated_start']
constructor: (@scope, @rs, @auth) ->
promise = @.loadTimeline()
promise.then null, @.onInitialDataError.bind(@)
isValid: (values) =>
return _.some values, (value) => @valid_fields.indexOf(value) != -1
filterValidTimelineItems: (timeline) =>
if timeline.data.values_diff
values = Object.keys(timeline.data.values_diff)
if values && values.length
if !@isValid(values)
return false
else if values[0] == 'attachments' && timeline.data.values_diff.attachments.new.length == 0
return false
return true
loadTimeline: () ->
user = @auth.getUser()
return @rs.timeline.profile(user.id).then (result) =>
@scope.result = result
console.log @scope.result.data
console.log result.data
@scope.timelineList = _.filter result.data, @filterValidTimelineItems
angular.module("taigaProfile")
.controller("ProfileTimeline", ProfileTimelineController)

View File

@ -12,6 +12,8 @@ TimelineAttachmentDirective = ($tgTemplate, $compile) ->
if is_image
template = $tgTemplate.get("profile/timeline/timeline-attachment-image.html")
else
template = $tgTemplate.get("profile/timeline/timeline-attachment.html")
$el.html(template)
$compile($el.contents())($scope)

View File

@ -1,4 +1,151 @@
TimelineItemDirective = ($tgTemplate, $compile, $navUrls) ->
timelineTitle = (timeline, event) ->
title = [
{ # NewMember
check: (timeline, event) ->
return event.obj == 'membership'
key: 'TIMELINE.NEW_MEMBER',
translate_params: ['project_name']
},
{ # NewProject
check: (timeline, event) ->
return event.obj == 'project' && event.type == 'create'
key: 'TIMELINE.NEW_PROJECT',
translate_params: ['username', 'project_name']
},
{ # NewAttachment
check: (timeline, event) ->
return event.type == 'change' && timeline.data.values_diff.attachments
key: 'TIMELINE.UPLOAD_ATTACHMENT',
translate_params: ['username', 'obj_name']
},
{ # NewUs
check: (timeline, event) ->
return event.obj == 'userstory' && event.type == 'create'
key: 'TIMELINE.US_CREATED',
translate_params: ['username', 'project_name', 'obj_name']
},
{ # NewIssue
check: (timeline, event) ->
return event.obj == 'issue' && event.type == 'create'
key: 'TIMELINE.ISSUE_CREATED',
translate_params: ['username', 'project_name', 'obj_name']
},
{ # NewWiki
check: (timeline, event) ->
return event.obj == 'wikipage' && event.type == 'create'
key: 'TIMELINE.WIKI_CREATED',
translate_params: ['username', 'project_name', 'obj_name']
},
{ # NewTask
check: (timeline, event) ->
return event.obj == 'task' && event.type == 'create'
key: 'TIMELINE.TASK_CREATED',
translate_params: ['username', 'project_name', 'obj_name']
},
{ # NewUsComment
check: (timeline, event) ->
return timeline.data.comment && event.obj == 'userstory'
key: 'TIMELINE.NEW_COMMENT_US',
translate_params: ['username', 'obj_name']
},
{ # NewIssueComment
check: (timeline, event) ->
return timeline.data.comment && event.obj == 'issue'
key: 'TIMELINE.NEW_COMMENT_ISSUE',
translate_params: ['username', 'obj_name']
},
{ # NewTask
check: (timeline, event) ->
return timeline.data.comment && event.obj == 'task'
key: 'TIMELINE.NEW_COMMENT_TASK'
translate_params: ['username', 'obj_name']
},
{ # UsToMilestone
check: (timeline, event, field_name) ->
if field_name == 'milestone' && event.type == 'change'
return timeline.data.values_diff.milestone[0] == null
return false
key: 'TIMELINE.US_ADDED_MILESTONE',
translate_params: ['username', 'obj_name', 'sprint_name']
},
{ # UsToBacklog
check: (timeline, event, field_name) ->
if field_name == 'milestone' && event.type == 'change'
return timeline.data.values_diff.milestone[1] == null
return false
key: 'TIMELINE.US_REMOVED_FROM_MILESTONE',
translate_params: ['username', 'obj_name']
},
{ # Blocked
check: (timeline, event) ->
if event.type == 'change' && timeline.data.values_diff.is_blocked
return timeline.data.values_diff.is_blocked[1] == true
return false
key: 'TIMELINE.BLOCKED',
translate_params: ['username', 'obj_name']
},
{ # UnBlocked
check: (timeline, event) ->
if event.type == 'change' && timeline.data.values_diff.is_blocked
return timeline.data.values_diff.is_blocked[1] == false
return false
key: 'TIMELINE.UNBLOCKED',
translate_params: ['username', 'obj_name']
},
{ # MilestoneUpdated
check: (timeline, event) ->
return event.obj == 'milestone' && event.type == 'change'
key: 'TIMELINE.MILESTONE_UPDATED',
translate_params: ['username', 'obj_name']
},
{ # WikiUpdated
check: (timeline, event) ->
return event.obj == 'wikipage' && event.type == 'change'
key: 'TIMELINE.WIKI_UPDATED',
translate_params: ['username', 'obj_name']
},
{ # UsUpdated
check: (timeline, event) ->
return event.obj == 'userstory' && event.type == 'change'
key: 'TIMELINE.US_UPDATED',
translate_params: ['username', 'field_name', 'obj_name']
},
{ # IssueUpdated
check: (timeline, event) ->
return event.obj == 'issue' && event.type == 'change'
key: 'TIMELINE.ISSUE_UPDATED',
translate_params: ['username', 'field_name', 'obj_name']
},
{ # TaskUpdated
check: (timeline, event) ->
return event.obj == 'task' && event.type == 'change'
key: 'TIMELINE.TASK_UPDATED',
translate_params: ['username', 'field_name', 'obj_name']
}
]
if timeline.data.values_diff
field_name = Object.keys(timeline.data.values_diff)[0]
return _.find title, (obj) ->
return obj.check(timeline, event, field_name)
TimelineItemDirective = ($tgTemplate, $compile, $navUrls, $translate, $sce) ->
fieldTranslationKey = {
'status': 'COMMON.FIELDS.STATUS',
'subject': 'COMMON.FIELDS.SUBJECT',
'description': 'COMMON.FIELDS.DESCRIPTION',
'points': 'COMMON.FIELDS.POINTS',
'severity': 'ISSUES.FIELDS.SEVERITY',
'priority': 'ISSUES.FIELDS.PRIORITY',
'type': 'ISSUES.FIELDS.TYPE',
'is_iocaine': 'TASK.FIELDS.IS_IOCAINE'
}
parseEventType = (event_type) ->
event_type = event_type.split(".")
@ -8,53 +155,100 @@ TimelineItemDirective = ($tgTemplate, $compile, $navUrls) ->
type: event_type[2]
}
getUrl = (timeline, event) ->
getDetailObjUrl = (event) ->
url = {
"issue": "project-issues-detail",
"wiki": "project-wiki-page",
"task": "project-tasks-detail",
"userstories": "project-userstories-detail"
"issue": ["project-issues-detail", ":project=activity.project.slug,ref=activity.obj.ref"],
"wikipage": ["project-wiki-page", ":project=activity.project.slug,slug=activity.obj.slug"],
"task": ["project-tasks-detail", ":project=activity.project.slug,ref=activity.obj.ref"],
"userstory": ["project-userstories-detail", ":project=activity.project.slug,ref=activity.obj.ref"],
"milestone": ["project-taskboard", ":project=activity.project.slug,sprint=activity.obj.slug"]
}
params = {project: timeline.data.project.slug, ref: timeline.data[event.obj].ref}
return url[event.obj][0] + url[event.obj][1]
return $navUrls.resolve(url[event.obj], params)
getLink = (url, text, title) ->
title = title || text
getTemplate = (timeline, event) ->
template = ""
return $('<a>')
.attr('tg-nav', url)
.text(text)
.attr('title', title)
.prop('outerHTML')
if event.type == 'change'
if timeline.data.comment.length
template = "profile/timeline/comment-timeline.html"
else if timeline.data.values_diff.attachments
template = "profile/timeline/attachment-timeline.html"
translate_params = {
username: (timeline) ->
user = timeline.data.user
title_attr = $translate.instant('COMMON.SEE_USER_PROFILE', {username: user.username})
url = 'user-profile:username=activity.user.username'
return getLink(url, user.username, title_attr)
return $tgTemplate.get(template)
field_name: (timeline) ->
field_name = Object.keys(timeline.data.values_diff)[0]
return $translate.instant(fieldTranslationKey[field_name])
project_name: (timeline) ->
url = 'project:project=activity.project.slug'
return getLink(url, timeline.data.project.name)
sprint_name: (timeline) ->
url = 'project-taskboard:project=activity.project.slug,sprint=activity.sprint.slug'
return getLink(url, timeline.data.milestone.name)
obj_name: (timeline, event) ->
obj = getTimelineObj(timeline, event)
url = getDetailObjUrl(event)
if event.obj == 'wikipage'
text = obj.slug
else if event.obj == 'milestone'
text = obj.name
else
text = '#' + obj.ref + ' ' + obj.subject
return getLink(url, text)
}
getTimelineObj = (timeline, event) ->
return timeline.data[event.obj]
getParams = (timeline, event, timeline_type) ->
params = {}
timeline_type.translate_params.forEach (param) ->
params[param] = translate_params[param](timeline, event)
return params
getTitle = (timeline, event) ->
type = timelineTitle(timeline, event)
return $translate.instant(type.key, getParams(timeline, event, type))
link = ($scope, $el, $attrs) ->
event = parseEventType($scope.timeline.event_type)
template = getTemplate($scope.timeline, event)
if !template
return ""
$scope.activity = {}
obj = $scope.timeline.data[event.obj]
$scope.activity.obj = getTimelineObj($scope.timeline, event)
$scope.activity.user = $scope.timeline.data.user
$scope.activity.project = $scope.timeline.data.project
$scope.activity.sprint = $scope.timeline.data.milestone
$scope.activity.title = getTitle($scope.timeline, event)
$scope.activity.created_formated = moment($scope.timeline.created).fromNow()
$scope.timeline.subject = obj.subject
$scope.timeline.ref = obj.ref
$scope.timeline.type = event.obj
$scope.timeline.created_formated = moment($scope.timeline.created).fromNow()
$scope.timeline.detail_url = getUrl($scope.timeline, event)
$el.html(template)
$compile($el.contents())($scope)
if $scope.timeline.data.values_diff?.attachments
$scope.activity.attachments = $scope.timeline.data.values_diff.attachments.new
return {
link: link
templateUrl: "profile/timeline/timeline-item.html"
scope: {
timeline: "=tgTimelineItem"
}
}
angular.module("taigaProfile")
.directive("tgTimelineItem", ["$tgTemplate", "$compile", "$tgNavUrls", TimelineItemDirective])
.directive("tgTimelineItem", ["$tgTemplate", "$compile", "$tgNavUrls", "$translate", "$sce", TimelineItemDirective])

View File

@ -100,6 +100,7 @@
"SAT": "Sat"
}
},
"SEE_USER_PROFILE": "See {{username }} profile",
"TAGS": {
"PLACEHOLDER": "I'm it! Tag me...",
"DELETE": "Delete tag",
@ -383,7 +384,7 @@
"TITLE": "Types",
"SUBTITLE": "Specify the types your issues could be",
"ISSUE_TITLE": "Issues types",
"ACTION_ADD": "Add new type"
"ACTION_ADD": "Add new type"
},
"ROLES": {
"SECTION_NAME": "Roles - {{projectName}}",
@ -924,6 +925,11 @@
"TITLE_NEXT_ISSUE": "next issue",
"ACTION_DELETE": "Delete issue",
"LIGHTBOX_TITLE_BLOKING_ISSUE": "Blocking issue",
"FIELDS": {
"PRIORITY": "Priority",
"SEVERITY": "Severity",
"TYPE": "Type"
},
"CONFIRM_PROMOTE": {
"TITLE": "Promote this issue to a new user story",
"MESSAGE": "Are you sure you want to create a new US from this Issue?"
@ -1090,5 +1096,29 @@
"LAST_EDIT": "last <br />edit",
"LAST_MODIFICATION": "last modification"
}
},
"TIMELINE": {
"UPLOAD_ATTACHMENT": "{{username}} has uploaded a new attachment in {{obj_name}}",
"US_CREATED": "{{username}} has created a new US in {{project_name}} {{obj_name}}",
"ISSUE_CREATED": "{{username}} has created a new Issue in {{project_name}} {{obj_name}}",
"TASK_CREATED": "{{username}} has created a new Task in {{project_name}} {{obj_name}}",
"WIKI_CREATED": "{{username}} has created a new Wiki page in {{project_name}} {{obj_name}}",
"NEW_PROJECT": "{{username}} has a new project {{project_name}}",
"MILESTONE_UPDATED": "{{username}} has updated the milestone {{obj_name}}",
"US_UPDATED": "{{username}} has updated the field \"{{field_name}}\" of the US {{obj_name}}",
"ISSUE_UPDATED": "{{username}} has updated the field \"{{field_name}}\" of the Issue {{obj_name}}",
"TASK_UPDATED": "{{username}} has updated the field \"{{field_name}}\" of the Task {{obj_name}}",
"WIKI_UPDATED": "{{username}} has update the Wiki page {{obj_name}}",
"NEW_COMMENT_US": "{{username}} has commented in the US {{obj_name}}",
"NEW_COMMENT_ISSUE": "{{username}} has commented in the Issue {{obj_name}}",
"NEW_COMMENT_TASK": "{{username}} has commented in the Task {{obj_name}}",
"NEW_MEMBER": "{{project_name}} has a new member",
"US_ADDED_MILESTONE": "{{username}} has added the US {{obj_name}} to {{sprint_name}}",
"US_REMOVED_FROM_MILESTONE": "{{username}} has added the US {{obj_name}} to the Backlog",
"BLOCKED": "{{username}} has blocked {{obj_name}}",
"UNBLOCKED": "{{username}} has unblocked {{obj_name}}"
},
"LANGUAGES": {
"ENGLISH": "English"
}
}

View File

@ -1,5 +1,5 @@
section.profile-timeline(ng-controller="ProfileTimeline as ctrl")
div(ng-repeat="timeline in result.data", tg-timeline-item="timeline")
div(ng-repeat="timeline in timelineList", tg-timeline-item="timeline")
- for (var x = 0; x < 3; x++)
// Simple message for favorites, updates, etc.
div.activity-simple

View File

@ -1,12 +0,0 @@
div.activity-comment
span.activity-date {{::timeline.created_formated}}
div.activity-info
div.profile-contact-picture
a(tg-nav="user-profile:username=timeline.data.user.username", title="{{::timeline.data.user.name }}")
img(ng-src="{{::timeline.data.user.photo}}", alt="{{::timeline.data.user.name}}")
p
a(tg-nav="user-profile:username=timeline.data.user.username", title="See {{::timeline.data.user.name }} profile") {{::timeline.data.user.name}}
span has commented in the {{::timeline.type }}
a(href="{{::timeline.detail_url}}", title="See #{{::timeline.ref}} {{::timeline.subject}}") \#{{::timeline.ref}} {{::timeline.subject}}
div.activity-comment-quote
p(ng-if="timeline.data.comment") "{{::timeline.data.comment}}"

View File

@ -1,12 +1,3 @@
div.activity-image
span.activity-date {{::timeline.created_formated}}
div.activity-info
div.profile-contact-picture
a(tg-nav="user-profile:username=timeline.data.user.username", title="{{::timeline.data.user.name }}")
img(ng-src="{{::timeline.data.user.photo}}", alt="{{::timeline.data.user.name}}")
p
a(tg-nav="user-profile:username=timeline.data.user.username", title="See {{::timeline.data.user.name }} profile") {{::timeline.data.user.name}}
span has uploaded an image in the {{::timeline.type }}
a(href="{{::timeline.detail_url}}", title="See #{{::timeline.ref}} {{::timeline.subject}}") \#{{::timeline.ref}} {{::timeline.subject}}
div(ng-repeat="attachment in timeline.data.values_diff.attachments.new")
div(tg-timeline-attachment="attachment")
p TODO: ATTACHMENT
p
a(ng-href="attachment.url"){{attachment.filename}}

View File

@ -0,0 +1,11 @@
div.activity-image
span.activity-date {{::activity.created_formated}}
div.activity-info
div.profile-contact-picture
a(tg-nav="user-profile:username=activity.user.username", title="{{::activity.user.name }}")
img(ng-src="{{::activity.user.photo}}", alt="{{::activity.user.name}}")
p(tg-compile-html="activity.title")
div(ng-repeat="attachment in activity.attachments")
div(tg-timeline-attachment="attachment")