Show likes, votes and watches list in user profile
parent
f52935f8c9
commit
331b14f13f
|
@ -28,7 +28,7 @@ resourceProvider = ($http, $urls) ->
|
||||||
service = {}
|
service = {}
|
||||||
|
|
||||||
service.contacts = (userId, options={}) ->
|
service.contacts = (userId, options={}) ->
|
||||||
url = $urls.resolve("contacts", userId)
|
url = $urls.resolve("user-contacts", userId)
|
||||||
httpOptions = {headers: {}}
|
httpOptions = {headers: {}}
|
||||||
|
|
||||||
if not options.enablePagination
|
if not options.enablePagination
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
section.profile-favorites
|
|
||||||
nav.profile-favorites-filters
|
|
||||||
a.active(href="", title="No Filter") all
|
|
||||||
a(href="", title="Only show your team") projects
|
|
||||||
a(href="", title="Only show people you follow") US
|
|
||||||
a(href="", title="Only show people follow you") tasks
|
|
|
@ -11,32 +11,30 @@ section.profile-contacts
|
||||||
div(ng-if="vm.isCurrentUser")
|
div(ng-if="vm.isCurrentUser")
|
||||||
p(translate="USER.PROFILE.CURRENT_USER_CONTACTS_EMPTY")
|
p(translate="USER.PROFILE.CURRENT_USER_CONTACTS_EMPTY")
|
||||||
p(translate="USER.PROFILE.CURRENT_USER_CONTACTS_EMPTY_EXPLAIN")
|
p(translate="USER.PROFILE.CURRENT_USER_CONTACTS_EMPTY_EXPLAIN")
|
||||||
|
//-
|
||||||
|
nav.profile-contact-filters
|
||||||
|
a.active(href="", title="No Filter") all
|
||||||
|
a(href="", title="Only show your team") team
|
||||||
|
a(href="", title="Only show people you follow") following
|
||||||
|
a(href="", title="Only show people follow you") followers
|
||||||
|
|
||||||
// nav.profile-contact-filters
|
div.list-itemtype-user(tg-repeat="contact in ::vm.contacts")
|
||||||
// a.active(href="", title="No Filter") all
|
a.list-itemtype-avatar(tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('name')}}")
|
||||||
// a(href="", title="Only show your team") team
|
img(ng-src="{{::contact.get('photo')}}", alt="{{::contact.get('full_name')}}")
|
||||||
// a(href="", title="Only show people you follow") following
|
|
||||||
// a(href="", title="Only show people follow you") followers
|
|
||||||
|
|
||||||
div.profile-contact-single(tg-repeat="contact in ::vm.contacts")
|
div.list-itemtype-user-data
|
||||||
div.profile-contact-picture
|
h2
|
||||||
a(tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('name') }}")
|
a(tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('full_name_display') }}") {{::contact.get('full_name_display')}}
|
||||||
img(ng-src="{{::contact.get('photo')}}", alt="{{::contact.get('full_name')}}")
|
|
||||||
|
p {{::contact.get('roles').join(", ")}}
|
||||||
|
p.extra-info(ng-if="contact.get('bio')") {{::contact.get('bio')}}
|
||||||
|
|
||||||
div.profile-contact-data
|
//-
|
||||||
h1
|
span.location todo
|
||||||
a(tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('full_name_display') }}")
|
div.profile-project-stats
|
||||||
| {{::contact.get('full_name_display')}}
|
div.stat-projects(title="2 projects")
|
||||||
|
span.icon.icon-project
|
||||||
p(ng-if="contact.bio") {{::contact.get('bio')}}
|
span.stat-num 2
|
||||||
|
div.stat-viewer(title="2 followers")
|
||||||
div.extra-info
|
span.icon.icon-open-eye
|
||||||
span.position {{::contact.get('roles').join(", ")}}
|
span.stat-num 4
|
||||||
// span.location todo
|
|
||||||
// div.profile-project-stats
|
|
||||||
// div.stat-projects(title="2 projects")
|
|
||||||
// span.icon.icon-project
|
|
||||||
// span.stat-num 2
|
|
||||||
// div.stat-viewer(title="2 followers")
|
|
||||||
// span.icon.icon-open-eye
|
|
||||||
// span.stat-num 4
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
FavItemDirective = ->
|
||||||
|
link = (scope, el, attrs, ctrl) ->
|
||||||
|
scope.vm = {item: scope.item}
|
||||||
|
|
||||||
|
templateUrl = (el, attrs) ->
|
||||||
|
if attrs.itemType == "project"
|
||||||
|
return "profile/profile-favs/items/project.html"
|
||||||
|
else # if attr.itemType in ["userstory", "task", "issue"]
|
||||||
|
return "profile/profile-favs/items/ticket.html"
|
||||||
|
|
||||||
|
return {
|
||||||
|
scope: {
|
||||||
|
"item": "=tgFavItem"
|
||||||
|
}
|
||||||
|
link: link
|
||||||
|
templateUrl: templateUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
angular.module("taigaProfile").directive("tgFavItem", FavItemDirective)
|
|
@ -0,0 +1,34 @@
|
||||||
|
.list-itemtype-project
|
||||||
|
.list-itemtype-project-data
|
||||||
|
h2
|
||||||
|
a(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=vm.item.get('slug')"
|
||||||
|
title="{{ ::vm.item.get('name') }}"
|
||||||
|
) {{ ::vm.item.get('name') }}
|
||||||
|
span.private(ng-if="::project.get('is_private')", title="{{'PROJECT.PRIVATE' | translate}}")
|
||||||
|
p {{ ::vm.item.get('description') }}
|
||||||
|
|
||||||
|
.list-itemtype-project-tags.tags-container(ng-if="::vm.item.get('tags_colors').size")
|
||||||
|
span.tag(
|
||||||
|
tg-repeat="tag in ::vm.item.get('tags_colors')"
|
||||||
|
style='border-left: 5px solid {{ ::tag.get("color") }};'
|
||||||
|
)
|
||||||
|
span.tag-name {{ ::tag.get('name') }}
|
||||||
|
|
||||||
|
.list-itemtype-track
|
||||||
|
span.list-itemtype-track-likers(
|
||||||
|
ng-class="{'active': vm.item.get('is_fan')}"
|
||||||
|
title="{{ 'PROJECT.LIKE_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_fans\")||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
span.icon
|
||||||
|
include ../../../../svg/like.svg
|
||||||
|
span {{ ::vm.item.get('total_fans') }}
|
||||||
|
|
||||||
|
span.list-itemtype-track-watchers(
|
||||||
|
ng-class="{'active': vm.item.get('is_watcher')}"
|
||||||
|
title="{{ 'PROJECT.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_watchers\")||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
span.icon
|
||||||
|
include ../../../../svg/watch.svg
|
||||||
|
span {{ ::vm.item.get('total_watchers') }}
|
|
@ -0,0 +1,80 @@
|
||||||
|
div.list-itemtype-ticket
|
||||||
|
a.list-itemtype-avatar(
|
||||||
|
href=""
|
||||||
|
ng-if="::vm.item.get('assigned_to')"
|
||||||
|
tg-nav="user-profile:username=vm.item.get('assigned_to_username')"
|
||||||
|
title="{{ ::vm.item.get('assigned_to_full_name') }}"
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
ng-src="{{ ::vm.item.get('assigned_to_photo') }}",
|
||||||
|
alt="{{ ::vm.item.get('assigned_to_full_name') }}"
|
||||||
|
)
|
||||||
|
|
||||||
|
a.list-itemtype-avatar(
|
||||||
|
href=""
|
||||||
|
ng-if="::!vm.item.get('assigned_to')",
|
||||||
|
title="{{ 'COMMON.ASSIGNED_TO.NOT_ASSIGNED'|translate }}"
|
||||||
|
)
|
||||||
|
img(
|
||||||
|
src="/images/unnamed.png",
|
||||||
|
alt="{{ 'COMMON.ASSIGNED_TO.NOT_ASSIGNED'|translate }}"
|
||||||
|
)
|
||||||
|
|
||||||
|
div.list-itemtype-ticket-data
|
||||||
|
p
|
||||||
|
span.ticket-project
|
||||||
|
| {{:: vm.item.get('project_name') }}
|
||||||
|
span.ticket-type(
|
||||||
|
ng-if="::vm.item.get('type') === 'userstory'"
|
||||||
|
translate="COMMON.USER_STORY"
|
||||||
|
)
|
||||||
|
span.ticket-type(
|
||||||
|
ng-if="::vm.item.get('type') === 'task'"
|
||||||
|
translate="COMMON.TASK"
|
||||||
|
)
|
||||||
|
span.ticket-type(
|
||||||
|
ng-if="::vm.item.get('type') === 'issue'"
|
||||||
|
translate="COMMON.ISSUE"
|
||||||
|
)
|
||||||
|
span.ticket-status(ng-style="::{'color': vm.item.get('status_color')}")
|
||||||
|
| {{:: vm.item.get('status') }}
|
||||||
|
h2
|
||||||
|
span.ticket-id(tg-bo-ref="vm.item.get('ref')")
|
||||||
|
a.ticket-title(
|
||||||
|
href="#"
|
||||||
|
ng-if="::vm.item.get('type') === 'userstory'"
|
||||||
|
tg-nav="project-userstories-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
|
||||||
|
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
|
||||||
|
)
|
||||||
|
| {{ ::vm.item.get('subject') }}
|
||||||
|
a.ticket-title(
|
||||||
|
href="#"
|
||||||
|
ng-if="::vm.item.get('type') === 'task'"
|
||||||
|
tg-nav="project-tasks-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
|
||||||
|
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
|
||||||
|
)
|
||||||
|
| {{ ::vm.item.get('subject') }}
|
||||||
|
a.ticket-title(
|
||||||
|
href="#"
|
||||||
|
ng-if="::vm.item.get('type') === 'issue'"
|
||||||
|
tg-nav="project-issues-detail:project=vm.item.get('project_slug'),ref=vm.item.get('ref')"
|
||||||
|
title="#{{ ::vm.item.get('ref') }} {{ ::vm.item.get('subject') }}"
|
||||||
|
)
|
||||||
|
| {{ ::vm.item.get('subject') }}
|
||||||
|
|
||||||
|
div.list-itemtype-track
|
||||||
|
span.list-itemtype-track-likers(
|
||||||
|
ng-class="{'active': vm.item.get('is_voter')}",
|
||||||
|
title="{{ 'COMMON.VOTE_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_voters\")||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
span.icon
|
||||||
|
include ../../../../svg/upvote.svg
|
||||||
|
span {{ ::vm.item.get('total_voters') }}
|
||||||
|
|
||||||
|
span.list-itemtype-track-watchers(
|
||||||
|
ng-class="{'active': vm.item.get('is_watcher')}"
|
||||||
|
title="{{ 'COMMON.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.get(\"total_watchers\")||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
span.icon
|
||||||
|
include ../../../../svg/watch.svg
|
||||||
|
span {{ ::vm.item.get('total_watchers') }}
|
|
@ -0,0 +1,168 @@
|
||||||
|
debounceLeading = @.taiga.debounceLeading
|
||||||
|
|
||||||
|
class FavsBaseController
|
||||||
|
constructor: ->
|
||||||
|
@._init()
|
||||||
|
|
||||||
|
#@._getItems = null # Define in inheritance classes
|
||||||
|
#
|
||||||
|
_init: ->
|
||||||
|
@.enableFilterByAll = true
|
||||||
|
@.enableFilterByProjects = true
|
||||||
|
@.enableFilterByUserStories = true
|
||||||
|
@.enableFilterByTasks = true
|
||||||
|
@.enableFilterByIssues = true
|
||||||
|
@.enableFilterByTextQuery = true
|
||||||
|
|
||||||
|
@._resetList()
|
||||||
|
@.q = null
|
||||||
|
@.type = null
|
||||||
|
|
||||||
|
_resetList: ->
|
||||||
|
@.items = Immutable.List()
|
||||||
|
@.scrollDisabled = false
|
||||||
|
@._page = 1
|
||||||
|
|
||||||
|
_enableLoadingSpinner: ->
|
||||||
|
@.isLoading = true
|
||||||
|
|
||||||
|
_disableLoadingSpinner: ->
|
||||||
|
@.isLoading = false
|
||||||
|
|
||||||
|
_enableScroll : ->
|
||||||
|
@.scrollDisabled = false
|
||||||
|
|
||||||
|
_disableScroll : ->
|
||||||
|
@.scrollDisabled = true
|
||||||
|
|
||||||
|
_checkIfHasMorePages: (hasNext) ->
|
||||||
|
if hasNext
|
||||||
|
@._page += 1
|
||||||
|
@._enableScroll()
|
||||||
|
else
|
||||||
|
@._disableScroll()
|
||||||
|
|
||||||
|
_checkIfHasNoResults: ->
|
||||||
|
@.hasNoResults = @.items.size == 0
|
||||||
|
|
||||||
|
loadItems: ->
|
||||||
|
@._enableLoadingSpinner()
|
||||||
|
@._disableScroll()
|
||||||
|
|
||||||
|
@._getItems(@.user.get("id"), @._page, @.type, @.q)
|
||||||
|
.then (response) =>
|
||||||
|
@.items = @.items.concat(response.get("data"))
|
||||||
|
|
||||||
|
@._checkIfHasMorePages(response.get("next"))
|
||||||
|
@._checkIfHasNoResults()
|
||||||
|
@._disableLoadingSpinner()
|
||||||
|
|
||||||
|
return @.items
|
||||||
|
.catch =>
|
||||||
|
@._disableLoadingSpinner()
|
||||||
|
|
||||||
|
return @.items
|
||||||
|
|
||||||
|
################################################
|
||||||
|
## Filtre actions
|
||||||
|
################################################
|
||||||
|
filterByTextQuery: debounceLeading 500, ->
|
||||||
|
@._resetList()
|
||||||
|
@.loadItems()
|
||||||
|
|
||||||
|
showAll: ->
|
||||||
|
if @.type isnt null
|
||||||
|
@.type = null
|
||||||
|
@._resetList()
|
||||||
|
@.loadItems()
|
||||||
|
|
||||||
|
showProjectsOnly: ->
|
||||||
|
if @.type isnt "project"
|
||||||
|
@.type = "project"
|
||||||
|
@._resetList()
|
||||||
|
@.loadItems()
|
||||||
|
|
||||||
|
showUserStoriesOnly: ->
|
||||||
|
if @.type isnt "userstory"
|
||||||
|
@.type = "userstory"
|
||||||
|
@._resetList()
|
||||||
|
@.loadItems()
|
||||||
|
|
||||||
|
showTasksOnly: ->
|
||||||
|
if @.type isnt "task"
|
||||||
|
@.type = "task"
|
||||||
|
@._resetList()
|
||||||
|
@.loadItems()
|
||||||
|
|
||||||
|
showIssuesOnly: ->
|
||||||
|
if @.type isnt "issue"
|
||||||
|
@.type = "issue"
|
||||||
|
@._resetList()
|
||||||
|
@.loadItems()
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## Liked
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
class ProfileLikedController extends FavsBaseController
|
||||||
|
@.$inject = [
|
||||||
|
"tgUserService",
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@userService) ->
|
||||||
|
super()
|
||||||
|
@.enableFilterByAll = false
|
||||||
|
@.enableFilterByProjects = false
|
||||||
|
@.enableFilterByUserStories = false
|
||||||
|
@.enableFilterByTasks = false
|
||||||
|
@.enableFilterByIssues = false
|
||||||
|
@.enableFilterByTextQuery = true
|
||||||
|
@._getItems = @userService.getLiked
|
||||||
|
|
||||||
|
|
||||||
|
angular.module("taigaProfile")
|
||||||
|
.controller("ProfileLiked", ProfileLikedController)
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## Voted
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
class ProfileVotedController extends FavsBaseController
|
||||||
|
@.$inject = [
|
||||||
|
"tgUserService",
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@userService) ->
|
||||||
|
super()
|
||||||
|
@.enableFilterByAll = true
|
||||||
|
@.enableFilterByProjects = false
|
||||||
|
@.enableFilterByUserStories = true
|
||||||
|
@.enableFilterByTasks = true
|
||||||
|
@.enableFilterByIssues = true
|
||||||
|
@.enableFilterByTextQuery = true
|
||||||
|
@._getItems = @userService.getVoted
|
||||||
|
|
||||||
|
|
||||||
|
angular.module("taigaProfile")
|
||||||
|
.controller("ProfileVoted", ProfileVotedController)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## Watched
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
class ProfileWatchedController extends FavsBaseController
|
||||||
|
@.$inject = [
|
||||||
|
"tgUserService",
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@userService) ->
|
||||||
|
super()
|
||||||
|
@._getItems = @userService.getWatched
|
||||||
|
|
||||||
|
|
||||||
|
angular.module("taigaProfile")
|
||||||
|
.controller("ProfileWatched", ProfileWatchedController)
|
||||||
|
|
|
@ -0,0 +1,679 @@
|
||||||
|
describe "ProfileLiked", ->
|
||||||
|
$controller = null
|
||||||
|
provide = null
|
||||||
|
$rootScope = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
user = Immutable.fromJS({id: 2})
|
||||||
|
|
||||||
|
_mockUserService = () ->
|
||||||
|
mocks.userServices = {
|
||||||
|
getLiked: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgUserService", mocks.userServices
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockUserService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = (callback) ->
|
||||||
|
inject (_$controller_, _$rootScope_) ->
|
||||||
|
$rootScope = _$rootScope_
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaProfile"
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
it "load paginated items", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileLiked", $scope, {user: user})
|
||||||
|
|
||||||
|
items1 = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
items2 = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 4},
|
||||||
|
{id: 5},
|
||||||
|
],
|
||||||
|
next: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getLiked.withArgs(user.get("id"), 1, null, null).promise().resolve(items1)
|
||||||
|
mocks.userServices.getLiked.withArgs(user.get("id"), 2, null, null).promise().resolve(items2)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = items1.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = expectItems.concat(items2.get("data"))
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.true
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "filter items by text query", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileLiked", $scope, {user: user})
|
||||||
|
|
||||||
|
textQuery = "_test_"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getLiked.withArgs(user.get("id"), 1, null, textQuery).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.q = textQuery
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.equal(textQuery)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "shou loading spinner during the call to the api", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileLiked", $scope, {user: user})
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mockPromise = mocks.userServices.getLiked.withArgs(user.get("id"), 1, null, null).promise()
|
||||||
|
|
||||||
|
expect(ctrl.isLoading).to.be.undefined
|
||||||
|
|
||||||
|
promise = ctrl.loadItems()
|
||||||
|
|
||||||
|
expect(ctrl.isLoading).to.be.true
|
||||||
|
|
||||||
|
mockPromise.resolve(items)
|
||||||
|
|
||||||
|
promise.then () =>
|
||||||
|
expect(ctrl.isLoading).to.be.false
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "shou no results placeholder", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileLiked", $scope, {user: user})
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [],
|
||||||
|
next: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getLiked.withArgs(user.get("id"), 1, null, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.hasNoResults).to.be.undefined
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expect(ctrl.hasNoResults).to.be.true
|
||||||
|
done()
|
||||||
|
|
||||||
|
|
||||||
|
describe "ProfileVoted", ->
|
||||||
|
$controller = null
|
||||||
|
provide = null
|
||||||
|
$rootScope = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
user = Immutable.fromJS({id: 2})
|
||||||
|
|
||||||
|
_mockUserService = () ->
|
||||||
|
mocks.userServices = {
|
||||||
|
getVoted: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgUserService", mocks.userServices
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockUserService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = (callback) ->
|
||||||
|
inject (_$controller_, _$rootScope_) ->
|
||||||
|
$rootScope = _$rootScope_
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaProfile"
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
it "load paginated items", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
items1 = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
items2 = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 4},
|
||||||
|
{id: 5},
|
||||||
|
],
|
||||||
|
next: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 1, null, null).promise().resolve(items1)
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 2, null, null).promise().resolve(items2)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = items1.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = expectItems.concat(items2.get("data"))
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.true
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "filter items by text query", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
textQuery = "_test_"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 1, null, textQuery).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.q = textQuery
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.equal(textQuery)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of user stories", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "userstory"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showUserStoriesOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of tasks", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "task"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showTasksOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of issues", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "issue"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showIssuesOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "shou loading spinner during the call to the api", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mockPromise = mocks.userServices.getVoted.withArgs(user.get("id"), 1, null, null).promise()
|
||||||
|
|
||||||
|
expect(ctrl.isLoading).to.be.undefined
|
||||||
|
|
||||||
|
promise = ctrl.loadItems()
|
||||||
|
|
||||||
|
expect(ctrl.isLoading).to.be.true
|
||||||
|
|
||||||
|
mockPromise.resolve(items)
|
||||||
|
|
||||||
|
promise.then () =>
|
||||||
|
expect(ctrl.isLoading).to.be.false
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "shou no results placeholder", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileVoted", $scope, {user: user})
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [],
|
||||||
|
next: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getVoted.withArgs(user.get("id"), 1, null, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.hasNoResults).to.be.undefined
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expect(ctrl.hasNoResults).to.be.true
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe "ProfileWatched", ->
|
||||||
|
$controller = null
|
||||||
|
provide = null
|
||||||
|
$rootScope = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
user = Immutable.fromJS({id: 2})
|
||||||
|
|
||||||
|
_mockUserService = () ->
|
||||||
|
mocks.userServices = {
|
||||||
|
getWatched: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgUserService", mocks.userServices
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockUserService()
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
|
_inject = (callback) ->
|
||||||
|
inject (_$controller_, _$rootScope_) ->
|
||||||
|
$rootScope = _$rootScope_
|
||||||
|
$controller = _$controller_
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaProfile"
|
||||||
|
_mocks()
|
||||||
|
_inject()
|
||||||
|
|
||||||
|
it "load paginated items", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
items1 = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
items2 = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 4},
|
||||||
|
{id: 5},
|
||||||
|
],
|
||||||
|
next: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, null, null).promise().resolve(items1)
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 2, null, null).promise().resolve(items2)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = items1.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = expectItems.concat(items2.get("data"))
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.true
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "filter items by text query", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
textQuery = "_test_"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, null, textQuery).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.q = textQuery
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.equal(textQuery)
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of projects", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "project"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showProjectsOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of user stories", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "userstory"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showUserStoriesOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of tasks", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "task"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showTasksOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "show only items of issues", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
type = "issue"
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, type, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.items.size).to.be.equal(0)
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.null
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
|
||||||
|
ctrl.showIssuesOnly().then () =>
|
||||||
|
expectItems = items.get("data")
|
||||||
|
|
||||||
|
expect(ctrl.items.equals(expectItems)).to.be.true
|
||||||
|
expect(ctrl.scrollDisabled).to.be.false
|
||||||
|
expect(ctrl.type).to.be.type
|
||||||
|
expect(ctrl.q).to.be.null
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "shou loading spinner during the call to the api", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
],
|
||||||
|
next: true
|
||||||
|
})
|
||||||
|
|
||||||
|
mockPromise = mocks.userServices.getWatched.withArgs(user.get("id"), 1, null, null).promise()
|
||||||
|
|
||||||
|
expect(ctrl.isLoading).to.be.undefined
|
||||||
|
|
||||||
|
promise = ctrl.loadItems()
|
||||||
|
|
||||||
|
expect(ctrl.isLoading).to.be.true
|
||||||
|
|
||||||
|
mockPromise.resolve(items)
|
||||||
|
|
||||||
|
promise.then () =>
|
||||||
|
expect(ctrl.isLoading).to.be.false
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "shou no results placeholder", (done) ->
|
||||||
|
$scope = $rootScope.$new()
|
||||||
|
ctrl = $controller("ProfileWatched", $scope, {user: user})
|
||||||
|
|
||||||
|
items = Immutable.fromJS({
|
||||||
|
data: [],
|
||||||
|
next: false
|
||||||
|
})
|
||||||
|
|
||||||
|
mocks.userServices.getWatched.withArgs(user.get("id"), 1, null, null).promise().resolve(items)
|
||||||
|
|
||||||
|
expect(ctrl.hasNoResults).to.be.undefined
|
||||||
|
|
||||||
|
ctrl.loadItems().then () =>
|
||||||
|
expect(ctrl.hasNoResults).to.be.true
|
||||||
|
done()
|
|
@ -0,0 +1,50 @@
|
||||||
|
base = {
|
||||||
|
scope: {},
|
||||||
|
bindToController: {
|
||||||
|
user: "="
|
||||||
|
type: "@"
|
||||||
|
q: "@"
|
||||||
|
scrollDisabled: "@"
|
||||||
|
isLoading: "@"
|
||||||
|
hasNoResults: "@"
|
||||||
|
}
|
||||||
|
controller: null, # Define in directives
|
||||||
|
controllerAs: "vm",
|
||||||
|
templateUrl: "profile/profile-favs/profile-favs.html",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## Liked
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
ProfileLikedDirective = () ->
|
||||||
|
return _.extend({}, base, {
|
||||||
|
controller: "ProfileLiked"
|
||||||
|
})
|
||||||
|
|
||||||
|
angular.module("taigaProfile").directive("tgProfileLiked", ProfileLikedDirective)
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## Voted
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
ProfileVotedDirective = () ->
|
||||||
|
return _.extend({}, base, {
|
||||||
|
controller: "ProfileVoted"
|
||||||
|
})
|
||||||
|
|
||||||
|
angular.module("taigaProfile").directive("tgProfileVoted", ProfileVotedDirective)
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
## Watched
|
||||||
|
####################################################
|
||||||
|
|
||||||
|
ProfileWatchedDirective = () ->
|
||||||
|
return _.extend({}, base, {
|
||||||
|
controller: "ProfileWatched"
|
||||||
|
})
|
||||||
|
|
||||||
|
angular.module("taigaProfile").directive("tgProfileWatched", ProfileWatchedDirective)
|
|
@ -0,0 +1,80 @@
|
||||||
|
section.profile-favs
|
||||||
|
div.profile-filter
|
||||||
|
div.searchbox(ng-if="::vm.enableFilterByTextQuery")
|
||||||
|
span.icon-search
|
||||||
|
input(
|
||||||
|
type="text"
|
||||||
|
ng-model="vm.q"
|
||||||
|
ng-change="vm.filterByTextQuery()"
|
||||||
|
placeholder="{{ 'USER.PROFILE_FAVS.FILTER_INPUT_PLACEHOLDER'|translate }}"
|
||||||
|
)
|
||||||
|
|
||||||
|
div.filters
|
||||||
|
a(
|
||||||
|
href=""
|
||||||
|
ng-if="::vm.enableFilterByAll"
|
||||||
|
ng-click="vm.showAll()"
|
||||||
|
ng-class="{active: vm.type === null}"
|
||||||
|
title="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_ALL_TITLE'|translate }}"
|
||||||
|
translate="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_ALL'|translate }}"
|
||||||
|
)
|
||||||
|
a(
|
||||||
|
href=""
|
||||||
|
ng-if="::vm.enableFilterByProjects"
|
||||||
|
ng-click="vm.showProjectsOnly()"
|
||||||
|
ng-class="{active: vm.type === 'project'}"
|
||||||
|
title="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_PROJECTS_TITLE'|translate }}"
|
||||||
|
translate="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_PROJECTS'|translate }}"
|
||||||
|
)
|
||||||
|
a(
|
||||||
|
href=""
|
||||||
|
ng-if="::vm.enableFilterByUserStories"
|
||||||
|
ng-click="vm.showUserStoriesOnly()"
|
||||||
|
ng-class="{active: vm.type === 'userstory'}",
|
||||||
|
title="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_USER_STORIES_TITLE'|translate }}"
|
||||||
|
translate="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_USER_STORIES'|translate }}"
|
||||||
|
)
|
||||||
|
a(
|
||||||
|
href=""
|
||||||
|
ng-if="::vm.enableFilterByTasks"
|
||||||
|
ng-click="vm.showTasksOnly()"
|
||||||
|
ng-class="{active: vm.type === 'task'}"
|
||||||
|
title="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_TASKS_TITLE'|translate }}"
|
||||||
|
translate="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_TASKS'|translate }}"
|
||||||
|
)
|
||||||
|
a(
|
||||||
|
href=""
|
||||||
|
ng-if="::vm.enableFilterByIssues"
|
||||||
|
ng-click="vm.showIssuesOnly()"
|
||||||
|
ng-class="{active: vm.type === 'issue'}"
|
||||||
|
title="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_ISSUES_TITLE'|translate }}"
|
||||||
|
translate="{{ 'USER.PROFILE_FAVS.FILTER_TYPE_ISSUES'|translate }}"
|
||||||
|
)
|
||||||
|
|
||||||
|
div(
|
||||||
|
infinite-scroll="vm.loadItems()"
|
||||||
|
infinite-scroll-distance="2"
|
||||||
|
infinite-scroll-disabled="vm.scrollDisabled"
|
||||||
|
)
|
||||||
|
div(
|
||||||
|
tg-repeat="item in vm.items track by $index"
|
||||||
|
ng-switch="item.get('type')"
|
||||||
|
)
|
||||||
|
div(ng-switch-when="project", tg-fav-item="item", item-type="project")
|
||||||
|
div(ng-switch-when="userstory", tg-fav-item="item", item-type="userstory")
|
||||||
|
div(ng-switch-when="task", tg-fav-item="item", item-type="task")
|
||||||
|
div(ng-switch-when="issue", tg-fav-item="item", item-type="issue")
|
||||||
|
|
||||||
|
div(ng-if="vm.isLoading")
|
||||||
|
div.spin
|
||||||
|
img(
|
||||||
|
src="/svg/spinner-circle.svg"
|
||||||
|
alt="{{ 'COMMON.LOADING'|translate }}"
|
||||||
|
)
|
||||||
|
|
||||||
|
.empty-search-results(ng-if="vm.hasNoResults && !vm.isLoading")
|
||||||
|
img(
|
||||||
|
src="../../images/search-empty.png"
|
||||||
|
alt="{{ 'USER.PROFILE_FAVS.EMPTY_TITLE' | translate }}"
|
||||||
|
)
|
||||||
|
p.title {{ 'USER.PROFILE_FAVS.EMPTY_TITLE' | translate }}
|
|
@ -0,0 +1,43 @@
|
||||||
|
.profile-favs {
|
||||||
|
border-top: 1px solid $whitish;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-filter {
|
||||||
|
align-items: center;
|
||||||
|
background: $whitish;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 1rem 0;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
.searchbox {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
.icon-search {
|
||||||
|
color: grayer;
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 1rem;
|
||||||
|
&:focus {
|
||||||
|
border-bottom: 1px solid $gray-light;
|
||||||
|
outline: none;
|
||||||
|
transition: border-bottom .3s ease-in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filters {
|
||||||
|
a {
|
||||||
|
color: $gray-light;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 .5rem;
|
||||||
|
&:hover,
|
||||||
|
&.active {
|
||||||
|
color: $blackish;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,37 +3,56 @@ section.profile-projects
|
||||||
div.spin
|
div.spin
|
||||||
img(src="/svg/spinner-circle.svg", alt="Loading...")
|
img(src="/svg/spinner-circle.svg", alt="Loading...")
|
||||||
|
|
||||||
div.empty-tab(ng-if="vm.projects && !vm.projects.size")
|
.empty-tab(ng-if="vm.projects && !vm.projects.size")
|
||||||
include ../../../svg/hide.svg
|
include ../../../svg/hide.svg
|
||||||
|
|
||||||
p(translate="USER.PROFILE.PROJECTS_EMPTY", translate-values="{username: vm.user.get('full_name_display')}")
|
p(
|
||||||
|
translate="USER.PROFILE.PROJECTS_EMPTY"
|
||||||
|
translate-values="{username: vm.user.get('full_name_display')}"
|
||||||
|
)
|
||||||
|
|
||||||
div.project-list-single(tg-repeat="project in vm.projects")
|
.list-itemtype-project(tg-repeat="project in vm.projects")
|
||||||
div.project-list-single-left
|
.list-itemtype-project-left
|
||||||
|
|
||||||
div.project-list-single-title
|
.project-list-single-title
|
||||||
h1
|
h2
|
||||||
a(href="#", tg-nav="project:project=project.get('slug')", title="{{ ::project.get('name') }}") {{::project.get('name')}}
|
a(
|
||||||
|
href="#"
|
||||||
|
tg-nav="project:project=project.get('slug')"
|
||||||
|
title="{{ ::project.get('name') }}"
|
||||||
|
) {{::project.get('name')}}
|
||||||
p {{ ::project.get('description') | limitTo:300 }}
|
p {{ ::project.get('description') | limitTo:300 }}
|
||||||
|
|
||||||
div.project-list-single-tags.tags-container(ng-if="::project.get('tags').size")
|
.list-itemtype-project-tags.tags-container(ng-if="::project.get('tags').size")
|
||||||
span.tag(style='border-left: 5px solid {{::tag.get("color")}};', tg-repeat="tag in ::project.get('colorized_tags')")
|
span.tag(
|
||||||
|
style='border-left: 5px solid {{::tag.get("color")}};'
|
||||||
|
tg-repeat="tag in ::project.get('colorized_tags')"
|
||||||
|
)
|
||||||
span.tag-name {{::tag.get('name')}}
|
span.tag-name {{::tag.get('name')}}
|
||||||
|
|
||||||
div.project-list-single-right
|
.list-itemtype-project-right
|
||||||
|
|
||||||
div.project-list-single-members
|
.list-itemtype-track
|
||||||
a(tg-repeat="contact in ::project.get('contacts')", tg-nav="user-profile:username=contact.get('username')", title="{{::contact.get('full_name')}}")
|
span.list-itemtype-track-likers(
|
||||||
|
ng-class="{'active': project.get('is_fan')}"
|
||||||
|
title="{{ 'PROJECT.LIKE_BUTTON.COUNTER_TITLE'|translate:{total:project.get(\"total_fans\")||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
span.icon
|
||||||
|
include ../../../svg/like.svg
|
||||||
|
span {{ ::project.get('total_fans') }}
|
||||||
|
|
||||||
|
span.list-itemtype-track-watchers(
|
||||||
|
ng-class="{'active': project.get('is_watcher')}"
|
||||||
|
title="{{ 'PROJECT.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:project.get(\"total_watchers\")||0}:'messageformat' }}"
|
||||||
|
)
|
||||||
|
span.icon
|
||||||
|
include ../../../svg/watch.svg
|
||||||
|
span {{ ::project.get('total_watchers') }}
|
||||||
|
|
||||||
|
.list-itemtype-project-members
|
||||||
|
a(
|
||||||
|
tg-repeat="contact in ::project.get('contacts')"
|
||||||
|
tg-nav="user-profile:username=contact.get('username')"
|
||||||
|
title="{{::contact.get('full_name')}}"
|
||||||
|
)
|
||||||
img(ng-src="{{::contact.get('photo')}}")
|
img(ng-src="{{::contact.get('photo')}}")
|
||||||
|
|
||||||
// div.project-list-single-right
|
|
||||||
// div.project-list-single-stats
|
|
||||||
// div.stat-comments(title="2 comments")
|
|
||||||
// span.icon.icon-comment
|
|
||||||
// span.stat-num 2
|
|
||||||
// div.stat-favorite.active(title="2 favorites")
|
|
||||||
// span.icon.icon-star-fill
|
|
||||||
// span.stat-num 4
|
|
||||||
// div.stat-viewer(title="2 followers")
|
|
||||||
// span.icon.icon-open-eye
|
|
||||||
// span.stat-num 4
|
|
||||||
|
|
|
@ -2,10 +2,12 @@ ProfileTabDirective = () ->
|
||||||
link = (scope, element, attrs, ctrl, transclude) ->
|
link = (scope, element, attrs, ctrl, transclude) ->
|
||||||
scope.tab = {}
|
scope.tab = {}
|
||||||
|
|
||||||
|
attrs.$observe "tgProfileTab", (name) ->
|
||||||
|
scope.tab.name = name
|
||||||
|
|
||||||
attrs.$observe "tabTitle", (title) ->
|
attrs.$observe "tabTitle", (title) ->
|
||||||
scope.tab.title = title
|
scope.tab.title = title
|
||||||
|
|
||||||
scope.tab.name = attrs.tgProfileTab
|
|
||||||
scope.tab.icon = attrs.tabIcon
|
scope.tab.icon = attrs.tabIcon
|
||||||
scope.tab.active = !!attrs.tabActive
|
scope.tab.active = !!attrs.tabActive
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
div
|
div
|
||||||
nav.profile-content-tabs
|
nav.profile-content-tabs
|
||||||
a.tab(ng-repeat="tab in ::vm.tabs", href="", title="{{tab.title}}", ng-class="{active: tab.active}" ng-click="vm.toggleTab(tab)")
|
a.tab(
|
||||||
|
href=""
|
||||||
|
ng-repeat="tab in ::vm.tabs"
|
||||||
|
title="{{tab.title}}"
|
||||||
|
ng-click="vm.toggleTab(tab)"
|
||||||
|
ng-class="{active: tab.active}"
|
||||||
|
)
|
||||||
span.icon(ng-class="::tab.icon")
|
span.icon(ng-class="::tab.icon")
|
||||||
span {{::tab.name}}
|
span {{::tab.name}}
|
||||||
|
|
||||||
ng-transclude
|
ng-transclude
|
||||||
|
|
|
@ -2,16 +2,48 @@ div.profile.centered(ng-if="vm.user")
|
||||||
div(tg-profile-bar, user="vm.user", isCurrentUser="vm.isCurrentUser")
|
div(tg-profile-bar, user="vm.user", isCurrentUser="vm.isCurrentUser")
|
||||||
div.main
|
div.main
|
||||||
div.timeline-wrapper(tg-profile-tabs)
|
div.timeline-wrapper(tg-profile-tabs)
|
||||||
div(tg-profile-tab="activity", tab-title="{{'USER.PROFILE.ACTIVITY_TAB' | translate}}", tab-icon="icon-timeline", tab-active)
|
div(
|
||||||
div(tg-user-timeline, user="vm.user", current-user="vm.isCurrentUser")
|
tg-profile-tab="{{'USER.PROFILE.TABS.ACTIVITY_TAB' | translate}}"
|
||||||
|
tab-title="{{'USER.PROFILE.TABS.ACTIVITY_TAB_TITLE' | translate}}"
|
||||||
|
tab-icon="icon-timeline"
|
||||||
|
tab-active
|
||||||
|
)
|
||||||
|
div(tg-user-timeline, user="vm.user", current-user="vm.isCurrentUser")
|
||||||
|
|
||||||
div(tab-disabled="{{vm.isCurrentUser}}", tg-profile-tab="projects", tab-title="{{'USER.PROFILE.PROJECTS_TAB' | translate}}", tab-icon="icon-project")
|
div(
|
||||||
div(tg-profile-projects, user="vm.user")
|
tg-profile-tab="{{'USER.PROFILE.TABS.PROJECTS_TAB' | translate}}"
|
||||||
|
tab-title="{{'USER.PROFILE.TABS.PROJECTS_TAB_TITLE' | translate}}"
|
||||||
|
tab-icon="icon-project"
|
||||||
|
tab-disabled="{{vm.isCurrentUser}}"
|
||||||
|
)
|
||||||
|
div(tg-profile-projects, user="vm.user")
|
||||||
|
|
||||||
div(tg-profile-tab="contacts", tab-title="{{'USER.PROFILE.CONTACTS_TAB' | translate}}", tab-icon="icon-team")
|
div(
|
||||||
div(tg-profile-contacts, user="vm.user")
|
tg-profile-tab="{{'USER.PROFILE.TABS.LIKES_TAB' | translate}}"
|
||||||
|
tab-title="{{'USER.PROFILE.TABS.LIKES_TAB_TITLE' | translate}}"
|
||||||
|
tab-icon="icon-heart"
|
||||||
|
)
|
||||||
|
div(tg-profile-liked, user="vm.user")
|
||||||
|
|
||||||
// div(tg-profile-tab="favorites", tab-title="{{'USER.PROFILE.FAVORITES_TAB' | translate}}", tab-icon="icon-star-fill")
|
div(
|
||||||
// include includes/profile-favorites
|
tg-profile-tab="{{'USER.PROFILE.TABS.VOTES_TAB' | translate}}"
|
||||||
|
tab-title="{{'USER.PROFILE.TABS.VOTES_TAB_TITLE' | translate}}"
|
||||||
|
tab-icon="icon-caret-up"
|
||||||
|
)
|
||||||
|
div(tg-profile-voted, user="vm.user")
|
||||||
|
|
||||||
|
div(
|
||||||
|
tg-profile-tab="{{'USER.PROFILE.TABS.WATCHED_TAB' | translate}}"
|
||||||
|
tab-title="{{'USER.PROFILE.TABS.WATCHED_TAB_TITLE' | translate}}"
|
||||||
|
tab-icon="icon-eye"
|
||||||
|
)
|
||||||
|
div(tg-profile-watched, user="vm.user")
|
||||||
|
|
||||||
|
div(
|
||||||
|
tg-profile-tab="{{'USER.PROFILE.TABS.CONTACTS_TAB' | translate}}"
|
||||||
|
tab-title="{{'USER.PROFILE.TABS.CONTACTS_TAB_TITLE' | translate}}"
|
||||||
|
tab-icon="icon-team"
|
||||||
|
)
|
||||||
|
div(tg-profile-contacts, user="vm.user")
|
||||||
|
|
||||||
include includes/profile-sidebar
|
include includes/profile-sidebar
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
.profile-favorites {
|
|
||||||
border-top: 1px solid $whitish;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.profile-favorites-filters {
|
|
||||||
align-self: flex-start;
|
|
||||||
display: flex;
|
|
||||||
a {
|
|
||||||
border-bottom: 2px solid $white;
|
|
||||||
color: $gray-light;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
transition: all .2s linear;
|
|
||||||
&:hover,
|
|
||||||
&.active {
|
|
||||||
border-bottom: 2px solid $gray-light;
|
|
||||||
color: $primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -51,6 +51,25 @@ Resource = (urlsService, http, paginateResponseService) ->
|
||||||
result = Immutable.fromJS(result)
|
result = Immutable.fromJS(result)
|
||||||
return paginateResponseService(result)
|
return paginateResponseService(result)
|
||||||
|
|
||||||
|
service.likeProject = (projectId) ->
|
||||||
|
url = urlsService.resolve("project-like", projectId)
|
||||||
|
return http.post(url)
|
||||||
|
|
||||||
|
service.unlikeProject = (projectId) ->
|
||||||
|
url = urlsService.resolve("project-unlike", projectId)
|
||||||
|
return http.post(url)
|
||||||
|
|
||||||
|
service.watchProject = (projectId, notifyPolicy) ->
|
||||||
|
data = {
|
||||||
|
notify_policy: notifyPolicy
|
||||||
|
}
|
||||||
|
url = urlsService.resolve("project-watch", projectId)
|
||||||
|
return http.post(url, data)
|
||||||
|
|
||||||
|
service.unwatchProject = (projectId) ->
|
||||||
|
url = urlsService.resolve("project-unwatch", projectId)
|
||||||
|
return http.post(url)
|
||||||
|
|
||||||
return () ->
|
return () ->
|
||||||
return {"projects": service}
|
return {"projects": service}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ Resource = (urlsService, http, paginateResponseService) ->
|
||||||
return Immutable.fromJS(result.data)
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
service.getStats = (userId) ->
|
service.getStats = (userId) ->
|
||||||
url = urlsService.resolve("stats", userId)
|
url = urlsService.resolve("user-stats", userId)
|
||||||
|
|
||||||
httpOptions = {
|
httpOptions = {
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -32,7 +32,7 @@ Resource = (urlsService, http, paginateResponseService) ->
|
||||||
return Immutable.fromJS(result.data)
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
service.getContacts = (userId) ->
|
service.getContacts = (userId) ->
|
||||||
url = urlsService.resolve("contacts", userId)
|
url = urlsService.resolve("user-contacts", userId)
|
||||||
|
|
||||||
httpOptions = {
|
httpOptions = {
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -44,6 +44,45 @@ Resource = (urlsService, http, paginateResponseService) ->
|
||||||
.then (result) ->
|
.then (result) ->
|
||||||
return Immutable.fromJS(result.data)
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
service.getLiked = (userId, page, type, q) ->
|
||||||
|
url = urlsService.resolve("user-liked", userId)
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
params.page = page if page?
|
||||||
|
params.type = type if type?
|
||||||
|
params.q = q if q?
|
||||||
|
|
||||||
|
return http.get(url, params)
|
||||||
|
.then (result) ->
|
||||||
|
result = Immutable.fromJS(result)
|
||||||
|
return paginateResponseService(result)
|
||||||
|
|
||||||
|
service.getVoted = (userId, page, type, q) ->
|
||||||
|
url = urlsService.resolve("user-voted", userId)
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
params.page = page if page?
|
||||||
|
params.type = type if type?
|
||||||
|
params.q = q if q?
|
||||||
|
|
||||||
|
return http.get(url, params)
|
||||||
|
.then (result) ->
|
||||||
|
result = Immutable.fromJS(result)
|
||||||
|
return paginateResponseService(result)
|
||||||
|
|
||||||
|
service.getWatched = (userId, page, type, q) ->
|
||||||
|
url = urlsService.resolve("user-watched", userId)
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
params.page = page if page?
|
||||||
|
params.type = type if type?
|
||||||
|
params.q = q if q?
|
||||||
|
|
||||||
|
return http.get(url, params)
|
||||||
|
.then (result) ->
|
||||||
|
result = Immutable.fromJS(result)
|
||||||
|
return paginateResponseService(result)
|
||||||
|
|
||||||
service.getProfileTimeline = (userId, page) ->
|
service.getProfileTimeline = (userId, page) ->
|
||||||
params = {
|
params = {
|
||||||
page: page
|
page: page
|
||||||
|
|
|
@ -3,7 +3,13 @@ taiga = @.taiga
|
||||||
truncate = taiga.truncate
|
truncate = taiga.truncate
|
||||||
|
|
||||||
|
|
||||||
class AppMetaService extends taiga.Service = ->
|
class AppMetaService
|
||||||
|
@.$inject = [
|
||||||
|
"$rootScope"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@rootScope) ->
|
||||||
|
|
||||||
_set: (key, value) ->
|
_set: (key, value) ->
|
||||||
return if not key
|
return if not key
|
||||||
|
|
||||||
|
@ -60,12 +66,19 @@ class AppMetaService extends taiga.Service = ->
|
||||||
@.setOpenGraphMetas(title, description)
|
@.setOpenGraphMetas(title, description)
|
||||||
|
|
||||||
addMobileViewport: () ->
|
addMobileViewport: () ->
|
||||||
$('head').append(
|
$("head").append(
|
||||||
'<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">'
|
"<meta name=\"viewport\"
|
||||||
|
content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0\">"
|
||||||
)
|
)
|
||||||
|
|
||||||
removeMobileViewport: () ->
|
removeMobileViewport: () ->
|
||||||
$('meta[name="viewport"]').remove()
|
$("meta[name=\"viewport\"]").remove()
|
||||||
|
|
||||||
|
setfn: (fn) ->
|
||||||
|
@._listener() if @.listener
|
||||||
|
|
||||||
|
@._listener = @rootScope.$watchCollection fn, (metas) =>
|
||||||
|
@.setAll(metas.title, metas.description)
|
||||||
|
|
||||||
|
|
||||||
angular.module("taigaCommon").service("tgAppMetaService", AppMetaService)
|
angular.module("taigaCommon").service("tgAppMetaService", AppMetaService)
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
describe "AppMetaService", ->
|
describe "AppMetaService", ->
|
||||||
appMetaService = null
|
appMetaService = null
|
||||||
|
$rootScope = null
|
||||||
data = {
|
data = {
|
||||||
title: "--title--",
|
title: "--title--",
|
||||||
description: "--description--"
|
description: "--description--"
|
||||||
}
|
}
|
||||||
|
|
||||||
_inject = () ->
|
_inject = () ->
|
||||||
inject (_tgAppMetaService_) ->
|
inject (_tgAppMetaService_, _$rootScope_) ->
|
||||||
appMetaService = _tgAppMetaService_
|
appMetaService = _tgAppMetaService_
|
||||||
|
$rootScope = _$rootScope_
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
module "taigaCommon"
|
module "taigaCommon"
|
||||||
|
@ -53,3 +55,18 @@ describe "AppMetaService", ->
|
||||||
expect($("meta[property='og:description']")).to.have.attr("content", data.description)
|
expect($("meta[property='og:description']")).to.have.attr("content", data.description)
|
||||||
expect($("meta[property='og:image']")).to.have.attr("content", "#{window.location.origin}/images/logo-color.png")
|
expect($("meta[property='og:image']")).to.have.attr("content", "#{window.location.origin}/images/logo-color.png")
|
||||||
expect($("meta[property='og:url']")).to.have.attr("content", window.location.href)
|
expect($("meta[property='og:url']")).to.have.attr("content", window.location.href)
|
||||||
|
|
||||||
|
it "set function to set the metas", () ->
|
||||||
|
fn = () ->
|
||||||
|
return {
|
||||||
|
title: 'test',
|
||||||
|
description: 'test2'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
appMetaService.setAll = sinon.stub()
|
||||||
|
appMetaService.setfn(fn)
|
||||||
|
|
||||||
|
$rootScope.$digest()
|
||||||
|
|
||||||
|
expect(appMetaService.setAll).to.have.been.calledWith('test', 'test2')
|
||||||
|
|
|
@ -49,13 +49,7 @@ class CurrentUserService
|
||||||
|
|
||||||
loadProjects: () ->
|
loadProjects: () ->
|
||||||
return @projectsService.getProjectsByUserId(@._user.get("id"))
|
return @projectsService.getProjectsByUserId(@._user.get("id"))
|
||||||
.then (projects) =>
|
.then (projects) => @.setProjects(projects)
|
||||||
@._projects = @._projects.set("all", projects)
|
|
||||||
@._projects = @._projects.set("recents", projects.slice(0, 10))
|
|
||||||
|
|
||||||
@._projectsById = Immutable.fromJS(groupBy(projects.toJS(), (p) -> p.id))
|
|
||||||
|
|
||||||
return @.projects
|
|
||||||
|
|
||||||
disableJoyRide: (section) ->
|
disableJoyRide: (section) ->
|
||||||
if section
|
if section
|
||||||
|
@ -96,4 +90,12 @@ class CurrentUserService
|
||||||
@.loadProjects()
|
@.loadProjects()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
setProjects: (projects) ->
|
||||||
|
@._projects = @._projects.set("all", projects)
|
||||||
|
@._projects = @._projects.set("recents", projects.slice(0, 10))
|
||||||
|
|
||||||
|
@._projectsById = Immutable.fromJS(groupBy(projects.toJS(), (p) -> p.id))
|
||||||
|
|
||||||
|
return @.projects
|
||||||
|
|
||||||
angular.module("taigaCommon").service("tgCurrentUserService", CurrentUserService)
|
angular.module("taigaCommon").service("tgCurrentUserService", CurrentUserService)
|
||||||
|
|
|
@ -92,7 +92,7 @@ describe "tgCurrentUserService", ->
|
||||||
it "bulkUpdateProjectsOrder and reload projects", (done) ->
|
it "bulkUpdateProjectsOrder and reload projects", (done) ->
|
||||||
fakeData = [{id: 1, id: 2}]
|
fakeData = [{id: 1, id: 2}]
|
||||||
|
|
||||||
currentUserService.loadProjects = sinon.spy()
|
currentUserService.loadProjects = sinon.stub()
|
||||||
|
|
||||||
mocks.projectsService.bulkUpdateProjectsOrder.withArgs(fakeData).promise().resolve()
|
mocks.projectsService.bulkUpdateProjectsOrder.withArgs(fakeData).promise().resolve()
|
||||||
|
|
||||||
|
@ -101,6 +101,41 @@ describe "tgCurrentUserService", ->
|
||||||
|
|
||||||
done()
|
done()
|
||||||
|
|
||||||
|
it "loadProject and set it", (done) ->
|
||||||
|
user = Immutable.fromJS({id: 1, name: "fake1"})
|
||||||
|
project = Immutable.fromJS({id: 2, name: "fake2"})
|
||||||
|
|
||||||
|
currentUserService._user = user
|
||||||
|
currentUserService.setProjects = sinon.stub()
|
||||||
|
|
||||||
|
mocks.projectsService.getProjectsByUserId.withArgs(1).promise().resolve(project)
|
||||||
|
|
||||||
|
currentUserService.loadProjects().then () ->
|
||||||
|
expect(currentUserService.setProjects).to.have.been.calledWith(project)
|
||||||
|
|
||||||
|
done()
|
||||||
|
|
||||||
|
it "setProject", () ->
|
||||||
|
projectsRaw = [
|
||||||
|
{id: 1, name: "fake1"},
|
||||||
|
{id: 2, name: "fake2"},
|
||||||
|
{id: 3, name: "fake3"},
|
||||||
|
{id: 4, name: "fake4"}
|
||||||
|
]
|
||||||
|
projectsRawById = {
|
||||||
|
1: {id: 1, name: "fake1"},
|
||||||
|
2: {id: 2, name: "fake2"},
|
||||||
|
3: {id: 3, name: "fake3"},
|
||||||
|
4: {id: 4, name: "fake4"}
|
||||||
|
}
|
||||||
|
projects = Immutable.fromJS(projectsRaw)
|
||||||
|
|
||||||
|
currentUserService.setProjects(projects)
|
||||||
|
|
||||||
|
expect(currentUserService.projects.get('all').toJS()).to.be.eql(projectsRaw)
|
||||||
|
expect(currentUserService.projects.get('recents').toJS()).to.be.eql(projectsRaw)
|
||||||
|
expect(currentUserService.projectsById.toJS()).to.be.eql(projectsRawById)
|
||||||
|
|
||||||
it "is authenticated", () ->
|
it "is authenticated", () ->
|
||||||
currentUserService.getUser = sinon.stub()
|
currentUserService.getUser = sinon.stub()
|
||||||
currentUserService.getUser.returns({})
|
currentUserService.getUser.returns({})
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
taiga = @.taiga
|
taiga = @.taiga
|
||||||
|
bindMethods = taiga.bindMethods
|
||||||
|
|
||||||
|
|
||||||
class UserService extends taiga.Service
|
class UserService extends taiga.Service
|
||||||
@.$inject = ["tgResources"]
|
@.$inject = ["tgResources"]
|
||||||
|
|
||||||
constructor: (@rs) ->
|
constructor: (@rs) ->
|
||||||
|
bindMethods(@)
|
||||||
|
|
||||||
getUserByUserName: (username) ->
|
getUserByUserName: (username) ->
|
||||||
return @rs.users.getUserByUsername(username)
|
return @rs.users.getUserByUsername(username)
|
||||||
|
@ -11,6 +14,15 @@ class UserService extends taiga.Service
|
||||||
getContacts: (userId) ->
|
getContacts: (userId) ->
|
||||||
return @rs.users.getContacts(userId)
|
return @rs.users.getContacts(userId)
|
||||||
|
|
||||||
|
getLiked: (userId, pageNumber, objectType, textQuery) ->
|
||||||
|
return @rs.users.getLiked(userId, pageNumber, objectType, textQuery)
|
||||||
|
|
||||||
|
getVoted: (userId, pageNumber, objectType, textQuery) ->
|
||||||
|
return @rs.users.getVoted(userId, pageNumber, objectType, textQuery)
|
||||||
|
|
||||||
|
getWatched: (userId, pageNumber, objectType, textQuery) ->
|
||||||
|
return @rs.users.getWatched(userId, pageNumber, objectType, textQuery)
|
||||||
|
|
||||||
getStats: (userId) ->
|
getStats: (userId) ->
|
||||||
return @rs.users.getStats(userId)
|
return @rs.users.getStats(userId)
|
||||||
|
|
||||||
|
|
|
@ -32,19 +32,6 @@ describe "UserService", ->
|
||||||
_mocks()
|
_mocks()
|
||||||
_inject()
|
_inject()
|
||||||
|
|
||||||
it "get user contacts", () ->
|
|
||||||
userId = 2
|
|
||||||
|
|
||||||
contacts = [
|
|
||||||
{id: 1},
|
|
||||||
{id: 2},
|
|
||||||
{id: 3}
|
|
||||||
]
|
|
||||||
|
|
||||||
mocks.resources.users.getContacts.withArgs(userId).returns(true)
|
|
||||||
|
|
||||||
expect(userService.getContacts(userId)).to.be.true
|
|
||||||
|
|
||||||
it "attach user contacts to projects", (done) ->
|
it "attach user contacts to projects", (done) ->
|
||||||
userId = 2
|
userId = 2
|
||||||
|
|
||||||
|
@ -88,6 +75,75 @@ describe "UserService", ->
|
||||||
|
|
||||||
$rootScope.$apply()
|
$rootScope.$apply()
|
||||||
|
|
||||||
|
it "get user liked", (done) ->
|
||||||
|
userId = 2
|
||||||
|
pageNumber = 1
|
||||||
|
objectType = null
|
||||||
|
textQuery = null
|
||||||
|
|
||||||
|
liked = [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
]
|
||||||
|
|
||||||
|
mocks.resources.users.getLiked = sinon.stub()
|
||||||
|
mocks.resources.users.getLiked.withArgs(userId, pageNumber, objectType, textQuery)
|
||||||
|
.promise()
|
||||||
|
.resolve(liked)
|
||||||
|
|
||||||
|
userService.getLiked(userId, pageNumber, objectType, textQuery).then (_liked_) ->
|
||||||
|
expect(_liked_).to.be.eql(liked)
|
||||||
|
done()
|
||||||
|
|
||||||
|
$rootScope.$apply()
|
||||||
|
|
||||||
|
it "get user voted", (done) ->
|
||||||
|
userId = 2
|
||||||
|
pageNumber = 1
|
||||||
|
objectType = null
|
||||||
|
textQuery = null
|
||||||
|
|
||||||
|
voted = [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
]
|
||||||
|
|
||||||
|
mocks.resources.users.getVoted = sinon.stub()
|
||||||
|
mocks.resources.users.getVoted.withArgs(userId, pageNumber, objectType, textQuery)
|
||||||
|
.promise()
|
||||||
|
.resolve(voted)
|
||||||
|
|
||||||
|
userService.getVoted(userId, pageNumber, objectType, textQuery).then (_voted_) ->
|
||||||
|
expect(_voted_).to.be.eql(voted)
|
||||||
|
done()
|
||||||
|
|
||||||
|
$rootScope.$apply()
|
||||||
|
|
||||||
|
it "get user watched", (done) ->
|
||||||
|
userId = 2
|
||||||
|
pageNumber = 1
|
||||||
|
objectType = null
|
||||||
|
textQuery = null
|
||||||
|
|
||||||
|
watched = [
|
||||||
|
{id: 1},
|
||||||
|
{id: 2},
|
||||||
|
{id: 3}
|
||||||
|
]
|
||||||
|
|
||||||
|
mocks.resources.users.getWatched = sinon.stub()
|
||||||
|
mocks.resources.users.getWatched.withArgs(userId, pageNumber, objectType, textQuery)
|
||||||
|
.promise()
|
||||||
|
.resolve(watched)
|
||||||
|
|
||||||
|
userService.getWatched(userId, pageNumber, objectType, textQuery).then (_watched_) ->
|
||||||
|
expect(_watched_).to.be.eql(watched)
|
||||||
|
done()
|
||||||
|
|
||||||
|
$rootScope.$apply()
|
||||||
|
|
||||||
it "get user by username", (done) ->
|
it "get user by username", (done) ->
|
||||||
username = "username-1"
|
username = "username-1"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue