diff --git a/app/modules/profile/includes/profile-timeline.jade b/app/modules/profile/includes/profile-timeline.jade
deleted file mode 100644
index 7ec2c7ee..00000000
--- a/app/modules/profile/includes/profile-timeline.jade
+++ /dev/null
@@ -1,3 +0,0 @@
-section.profile-timeline(ng-controller="ProfileTimeline as ctrl")
- div(infinite-scroll="ctrl.loadTimeline()", infinite-scroll-distance="3", infinite-scroll-disabled='ctrl.loadingData')
- div(ng-repeat="timeline in ctrl.timelineList", tg-profile-timeline-item="timeline")
diff --git a/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.coffee b/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.coffee
index a4079994..09da8a2f 100644
--- a/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.coffee
+++ b/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.coffee
@@ -21,7 +21,7 @@ class ProfileTimelineItemTitle
if param == "username"
user = timeline.data.user
title_attr = @translate.instant('COMMON.SEE_USER_PROFILE', {username: user.username})
- url = 'user-profile:username=activity.user.username'
+ url = 'user-profile:username=vm.activity.user.username'
return @._getLink(url, user.username, title_attr)
else if param == 'field_name'
@@ -30,12 +30,12 @@ class ProfileTimelineItemTitle
return @translate.instant(@._fieldTranslationKey[field_name])
else if param == 'project_name'
- url = 'project:project=activity.project.slug'
+ url = 'project:project=vm.activity.project.slug'
return @._getLink(url, timeline.data.project.name)
else if param == 'sprint_name'
- url = 'project-taskboard:project=activity.project.slug,sprint=activity.sprint.slug'
+ url = 'project-taskboard:project=vm.activity.project.slug,sprint=vm.activity.sprint.slug'
return @._getLink(url, timeline.data.milestone.name)
diff --git a/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.spec.coffee b/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.spec.coffee
index 133dde8b..f9def537 100644
--- a/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.spec.coffee
+++ b/app/modules/profile/profile-timeline-item/profile-timeline-item-title.service.spec.coffee
@@ -52,7 +52,7 @@ describe "tgProfileTimelineItemTitle", ->
.returns('user-param')
usernamelink = sinon.match ((value) ->
- return value.username == 'xx'
+ return value.username == 'xx'
), "usernamelink"
mockTranslate.instant
@@ -113,7 +113,7 @@ describe "tgProfileTimelineItemTitle", ->
}
projectparam = sinon.match ((value) ->
- return value.project_name == 'project_name'
+ return value.project_name == 'project_name'
), "projectparam"
mockTranslate.instant
@@ -141,7 +141,7 @@ describe "tgProfileTimelineItemTitle", ->
}
milestoneparam = sinon.match ((value) ->
- return value.sprint_name == 'milestone_name'
+ return value.sprint_name == 'milestone_name'
), "milestoneparam"
mockTranslate.instant
diff --git a/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.coffee b/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.coffee
index e0cf1141..7ab2901c 100644
--- a/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.coffee
+++ b/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.coffee
@@ -1,31 +1,33 @@
class ProfileTimelineItemController
@.$inject = [
- "$scope",
"$sce",
"tgProfileTimelineItemType",
"tgProfileTimelineItemTitle"
]
- constructor: (@scope, @sce, @profileTimelineItemType, @profileTimelineItemTitle) ->
- event = @parseEventType(@scope.vm.timeline.event_type)
- type = @profileTimelineItemType.getType(@scope.vm.timeline, event)
+ constructor: (@sce, @profileTimelineItemType, @profileTimelineItemTitle) ->
+ timeline = @.timeline
+ event = @.parseEventType(timeline.event_type)
+ type = @profileTimelineItemType.getType(timeline, event)
@.activity = {}
- @.activity.user = @scope.vm.timeline.data.user
- @.activity.project = @scope.vm.timeline.data.project
- @.activity.sprint = @scope.vm.timeline.data.milestone
- @.activity.title = @profileTimelineItemTitle.getTitle(@scope.vm.timeline, event, type)
- @.activity.created_formated = moment(@scope.vm.timeline.created).fromNow()
+ @.activity.user = timeline.data.user
+ @.activity.project = timeline.data.project
+ @.activity.sprint = timeline.data.milestone
+ @.activity.title = @profileTimelineItemTitle.getTitle(timeline, event, type)
+ @.activity.created_formated = moment(timeline.created).fromNow()
+ #test
+ @.activity.obj = @.getObject(timeline, event)
if type.description
- @.activity.description = @sce.trustAsHtml(type.description(@scope.vm.timeline))
+ @.activity.description = @sce.trustAsHtml(type.description(timeline))
if type.member
- @.activity.member = type.member(@scope.vm.timeline)
+ @.activity.member = type.member(timeline)
- if @scope.vm.timeline.data.values_diff?.attachments
- @.activity.attachments = @scope.vm.timeline.data.values_diff.attachments.new
+ if timeline.data.values_diff?.attachments
+ @.activity.attachments = timeline.data.values_diff.attachments.new
parseEventType: (event_type) ->
event_type = event_type.split(".")
@@ -36,5 +38,9 @@ class ProfileTimelineItemController
type: event_type[2]
}
+ getObject: (timeline, event) ->
+ if timeline.data[event.obj]
+ return timeline.data[event.obj]
+
angular.module("taigaProfile")
.controller("ProfileTimelineItem", ProfileTimelineItemController)
diff --git a/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.spec.coffee b/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.spec.coffee
index 5f59fbd0..32edcf26 100644
--- a/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.spec.coffee
+++ b/app/modules/profile/profile-timeline-item/profile-timeline-item.controller.spec.coffee
@@ -72,7 +72,7 @@ describe "ProfileTimelineItemController", ->
it "basic activity fields filled", () ->
timeline = scope.vm.timeline
- myCtrl = controller("ProfileTimelineItem", {$scope: scope})
+ myCtrl = controller("ProfileTimelineItem", {$scope: scope}, {timeline: timeline})
expect(myCtrl.activity.user).to.be.equal(timeline.data.user)
expect(myCtrl.activity.project).to.be.equal(timeline.data.project)
@@ -94,7 +94,7 @@ describe "ProfileTimelineItemController", ->
mockType.description.withArgs(timeline).returns(description)
mockType.member.withArgs(timeline).returns(member)
- myCtrl = controller("ProfileTimelineItem", {$scope: scope})
+ myCtrl = controller("ProfileTimelineItem", {$scope: scope}, {timeline: timeline})
expect(myCtrl.activity.description).to.be.an('object') # $sce.trustAsHtml
expect(myCtrl.activity.member).to.be.equal(member)
diff --git a/app/modules/profile/profile-timeline-item/profile-timeline-item.jade b/app/modules/profile/profile-timeline-item/profile-timeline-item.jade
index 64471945..dbf10787 100644
--- a/app/modules/profile/profile-timeline-item/profile-timeline-item.jade
+++ b/app/modules/profile/profile-timeline-item/profile-timeline-item.jade
@@ -14,7 +14,7 @@ div.activity-image
.profile-member-picture
img(ng-src="{{::vm.activity.member.user.photo}}", alt="{{::vm.activity.member.user.name}}")
.activity-member-info
- a(tg-nav="user-profile:username=activity.member.user.username", title="{{::vm.activity.member.user.name }}")
+ a(tg-nav="user-profile:username=vm.activity.member.user.username", title="{{::vm.activity.member.user.name }}")
span {{::vm.activity.member.user.name}}
p {{::vm.activity.member.role.name}}
diff --git a/app/modules/profile/profile-timeline/profile-timeline.controller.coffee b/app/modules/profile/profile-timeline/profile-timeline.controller.coffee
index 714d89ae..db97b33a 100644
--- a/app/modules/profile/profile-timeline/profile-timeline.controller.coffee
+++ b/app/modules/profile/profile-timeline/profile-timeline.controller.coffee
@@ -25,59 +25,26 @@ mixOf = @.taiga.mixOf
class ProfileTimelineController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.FiltersMixin)
@.$inject = [
- "$tgResources",
- "$tgAuth"
+ "$tgAuth",
+ "tgProfileTimelineService"
]
- _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: (@rs, @auth) ->
- @.timelineList = []
- @.pagination = {page: 1}
+ constructor: (@auth, @profileTimelineService) ->
+ @.timelineList = Immutable.List()
+ @.page = 1
@.loadingData = false
- _isValidField: (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 !@._isValidField(values)
- return false
- else if values[0] == 'attachments' && timeline.data.values_diff.attachments.new.length == 0
- return false
-
- return true
-
loadTimeline: () ->
user = @auth.getUser()
@.loadingData = true
- return @rs.timeline.profile(user.id, @.pagination).then (result) =>
- newTimelineList = _.filter result.data, @._filterValidTimelineItems
- @.timelineList = @timelineList.concat(newTimelineList)
- @.pagination.page++
- @.loadingData = false
+ @profileTimelineService
+ .getTimeline(user.id, @.page)
+ .then (newTimelineList) =>
+ @.timelineList = @.timelineList.concat(newTimelineList)
+ @.page++
+ @.loadingData = false
angular.module("taigaProfile")
.controller("ProfileTimeline", ProfileTimelineController)
diff --git a/app/modules/profile/profile-timeline/profile-timeline.controller.spec.coffee b/app/modules/profile/profile-timeline/profile-timeline.controller.spec.coffee
index 18669f00..954560cb 100644
--- a/app/modules/profile/profile-timeline/profile-timeline.controller.spec.coffee
+++ b/app/modules/profile/profile-timeline/profile-timeline.controller.spec.coffee
@@ -1,13 +1,17 @@
describe "ProfileTimelineController", ->
myCtrl = scope = $q = provide = null
+ mocks = {}
+
mockUser = {id: 3}
- _mockTgResources = () ->
- provide.value "$tgResources", {
- timeline: {}
+ _mockProfileTimeline = () ->
+ mocks.profileTimelineService = {
+ getTimeline: sinon.stub()
}
+ provide.value "tgProfileTimelineService", mocks.profileTimelineService
+
_mockTgAuth = () ->
provide.value "$tgAuth", {
getUser: () ->
@@ -17,7 +21,7 @@ describe "ProfileTimelineController", ->
_mocks = () ->
module ($provide) ->
provide = $provide
- _mockTgResources()
+ _mockProfileTimeline()
_mockTgAuth()
return null
@@ -32,60 +36,31 @@ describe "ProfileTimelineController", ->
myCtrl = $controller "ProfileTimeline"
it "timelineList should be an array", () ->
- expect(myCtrl.timelineList).is.an("array")
-
+ expect(myCtrl.timelineList.toJS()).is.an("array")
it "pagination starts at 1", () ->
- expect(myCtrl.pagination.page).to.be.equal(1)
+ expect(myCtrl.page).to.be.equal(1)
describe "load timeline", () ->
thenStub = timelineList = null
beforeEach () ->
- timelineList = {
- data: [
- { # valid item
- data: {
- values_diff: {
- "status": "xx",
- "subject": "xx"
- }
- }
- },
- { # invalid item
- data: {
- values_diff: {
- "fake": "xx"
- }
- }
- },
- { # invalid item
- data: {
- values_diff: {
- "fake2": "xx"
- }
- }
- },
- { # valid item
- data: {
- values_diff: {
- "fake2": "xx",
- "milestone": "xx"
- }
- }
- }
- ]
- }
+ timelineList = Immutable.fromJS([
+ { fake: "fake"},
+ { fake: "fake"},
+ { fake: "fake"},
+ { fake: "fake"}
+ ])
thenStub = sinon.stub()
profileStub = sinon.stub()
- .withArgs(mockUser.id, myCtrl.pagination)
+ .withArgs(mockUser.id, myCtrl.page)
.returns({
then: thenStub
})
- myCtrl.rs.timeline.profile = profileStub
+ mocks.profileTimelineService.getTimeline = profileStub
it "the loadingData variable must be true during the timeline load", () ->
expect(myCtrl.loadingData).to.be.false
@@ -99,18 +74,17 @@ describe "ProfileTimelineController", ->
expect(myCtrl.loadingData).to.be.false
it "pagiantion increase one every call to loadTimeline", () ->
- expect(myCtrl.pagination.page).to.equal(1)
+ expect(myCtrl.page).to.equal(1)
myCtrl.loadTimeline()
thenStub.callArgWith(0, timelineList)
- expect(myCtrl.pagination.page).to.equal(2)
+ expect(myCtrl.page).to.equal(2)
- it "filter the invalid timeline items", () ->
+ it "timeline items", () ->
myCtrl.loadTimeline()
thenStub.callArgWith(0, timelineList)
- expect(myCtrl.timelineList[0]).to.be.equal(timelineList.data[0])
- expect(myCtrl.timelineList[1]).to.be.equal(timelineList.data[3])
+ expect(myCtrl.timelineList.size).to.be.eql(4)
diff --git a/app/modules/profile/profile-timeline/profile-timeline.directive.coffee b/app/modules/profile/profile-timeline/profile-timeline.directive.coffee
new file mode 100644
index 00000000..ae4ba91d
--- /dev/null
+++ b/app/modules/profile/profile-timeline/profile-timeline.directive.coffee
@@ -0,0 +1,9 @@
+ProfileTimelineDirective = ->
+ return {
+ templateUrl: "profile/profile-timeline/profile-timeline.html",
+ controller: "ProfileTimeline",
+ controllerAs: "vm",
+ scope: {}
+ }
+
+angular.module("taigaProfile").directive("tgProfileTimeline", ProfileTimelineDirective)
diff --git a/app/modules/profile/profile-timeline/profile-timeline.jade b/app/modules/profile/profile-timeline/profile-timeline.jade
new file mode 100644
index 00000000..20b6fdb5
--- /dev/null
+++ b/app/modules/profile/profile-timeline/profile-timeline.jade
@@ -0,0 +1,3 @@
+section.profile-timeline
+ div(infinite-scroll="vm.loadTimeline()", infinite-scroll-distance="3", infinite-scroll-disabled='vm.loadingData')
+ div(tg-repeat="timeline in vm.timelineList", tg-profile-timeline-item="timeline")
diff --git a/app/modules/profile/profile-timeline/profile-timeline.service.coffee b/app/modules/profile/profile-timeline/profile-timeline.service.coffee
new file mode 100644
index 00000000..0ac90906
--- /dev/null
+++ b/app/modules/profile/profile-timeline/profile-timeline.service.coffee
@@ -0,0 +1,51 @@
+taiga = @.taiga
+
+class ProfileTimelineService extends taiga.Service
+ @.$inject = ["$tgResources"]
+
+ constructor: (@rs) ->
+
+ _valid_fields: [
+ 'status',
+ 'subject',
+ 'description',
+ 'assigned_to',
+ 'points',
+ 'severity',
+ 'priority',
+ 'type',
+ 'attachments',
+ 'milestone',
+ 'is_blocked',
+ 'is_iocaine',
+ 'content_diff',
+ 'name',
+ 'estimated_finish',
+ 'estimated_start'
+ ]
+
+ _isValidField: (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 !@._isValidField(values)
+ return false
+ else if values[0] == 'attachments' &&
+ timeline.data.values_diff.attachments.new.length == 0
+ return false
+
+ return true
+
+ getTimeline: (userId, page) ->
+ return @rs.timeline.profile(userId, page)
+ .then (result) =>
+ newTimelineList = _.filter result.data, @._filterValidTimelineItems
+
+ return Immutable.fromJS(newTimelineList)
+
+
+angular.module("taigaProjects").service("tgProfileTimelineService", ProfileTimelineService)
diff --git a/app/modules/profile/profile-timeline/profile-timeline.service.spec.coffee b/app/modules/profile/profile-timeline/profile-timeline.service.spec.coffee
new file mode 100644
index 00000000..77445b3a
--- /dev/null
+++ b/app/modules/profile/profile-timeline/profile-timeline.service.spec.coffee
@@ -0,0 +1,113 @@
+describe "tgProfileTimelineService", ->
+ provide = null
+ $q = null
+ $rootScope = null
+ profileTimelineService = null
+ mocks = {}
+
+ _mockResources = () ->
+ mocks.resources = {}
+
+ mocks.resources.timeline = {
+ profile: sinon.stub()
+ }
+
+ provide.value "$tgResources", mocks.resources
+
+ _mocks = () ->
+ module ($provide) ->
+ provide = $provide
+ _mockResources()
+
+ return null
+
+ _setup = ->
+ _mocks()
+
+ _inject = (callback) ->
+ inject (_tgProfileTimelineService_, _$q_, _$rootScope_) ->
+ profileTimelineService = _tgProfileTimelineService_
+ $q = _$q_
+ $rootScope = _$rootScope_
+ callback() if callback
+
+ beforeEach ->
+ module "taigaProjects"
+ _setup()
+ _inject()
+
+ it "filter invalid timeline items", (done) ->
+ valid_items = {
+ data: [
+ { # valid item
+ data: {
+ values_diff: {
+ "status": "xx",
+ "subject": "xx"
+ }
+ }
+ },
+ { # invalid item
+ data: {
+ values_diff: {
+ "fake": "xx"
+ }
+ }
+ },
+ { # invalid item
+ data: {
+ values_diff: {
+ "fake2": "xx"
+ }
+ }
+ },
+ { # valid item
+ data: {
+ values_diff: {
+ "fake2": "xx",
+ "milestone": "xx"
+ }
+ }
+ },
+ { # invalid item
+ data: {
+ values_diff: {
+ attachments: {
+ new: []
+ }
+ }
+ }
+ },
+ { # valid item
+ data: {
+ values_diff: {
+ attachments: {
+ new: [1, 2]
+ }
+ }
+ }
+ }
+ ]
+ }
+
+ userId = 3
+ page = 2
+
+ mocks.resources.timeline.profile = (_userId_, _page_) ->
+ expect(_userId_).to.be.equal(userId)
+ expect(_page_).to.be.equal(page)
+
+ return $q (resolve, reject) ->
+ resolve(valid_items)
+
+ profileTimelineService.getTimeline(userId, page)
+ .then (_items_) ->
+ items = _items_.toJS()
+
+ expect(items[0]).to.be.eql(valid_items.data[0])
+ expect(items[1]).to.be.eql(valid_items.data[3])
+ expect(items[2]).to.be.eql(valid_items.data[5])
+
+ done()
+
+ $rootScope.$apply()
diff --git a/app/modules/profile/profile.jade b/app/modules/profile/profile.jade
index 88d88eb6..9264c001 100644
--- a/app/modules/profile/profile.jade
+++ b/app/modules/profile/profile.jade
@@ -7,7 +7,7 @@ div.profile.centered
div.content-wrapper
div.content
div(tg-profile-tab="activity", tab-title="Activity Tab", tab-icon="icon-timeline", tab-active)
- include includes/profile-timeline
+ div(tg-profile-timeline)
div(tg-profile-tab="projects", tab-title="Projects Tab", tab-icon="icon-project")
div(tg-profile-projects)