diff --git a/app/coffee/modules/resources.coffee b/app/coffee/modules/resources.coffee index 69730a00..ba1c1dc7 100644 --- a/app/coffee/modules/resources.coffee +++ b/app/coffee/modules/resources.coffee @@ -31,6 +31,7 @@ urls = { # User "users": "/users" + "by_username": "/users/by_username" "users-password-recovery": "/users/password_recovery" "users-change-password-from-recovery": "/users/change_password_from_recovery" "users-change-password": "/users/change_password" @@ -145,10 +146,6 @@ urls = { # locales "locales": "/locales" - - # users - "contacts": "/users/%s/contacts" - "stats": "/users/%s/stats" } # Initialize api urls service diff --git a/app/modules/profile/includes/profile-sidebar.jade b/app/modules/profile/includes/profile-sidebar.jade index 02ff3509..48e8d078 100644 --- a/app/modules/profile/includes/profile-sidebar.jade +++ b/app/modules/profile/includes/profile-sidebar.jade @@ -1,8 +1,9 @@ aside.profile-sidebar - h4(translate="USER.PROFILE_SIDEBAR.TITLE") - p(translate="USER.PROFILE_SIDEBAR.DESCRIPTION") - a.trans-button - span(translate="USER.PROFILE_SIDEBAR.ADD_INFO") + div(ng-if="::vm.isCurrentUser") + h4(translate="USER.PROFILE_SIDEBAR.TITLE") + p(translate="USER.PROFILE_SIDEBAR.DESCRIPTION") + a.trans-button + span(translate="USER.PROFILE_SIDEBAR.ADD_INFO") h4 span.icon.icon-help diff --git a/app/modules/profile/profile-bar/profile-bar.controller.coffee b/app/modules/profile/profile-bar/profile-bar.controller.coffee index ba41bd15..902679ec 100644 --- a/app/modules/profile/profile-bar/profile-bar.controller.coffee +++ b/app/modules/profile/profile-bar/profile-bar.controller.coffee @@ -1,16 +1,13 @@ class ProfileBarController @.$inject = [ - "$tgAuth", "tgUserService" ] - constructor: (@auth, @userService) -> - @.user = @auth.getUser() - + constructor: (@userService) -> @.loadStats() loadStats: () -> - return @userService.getStats(@.user.id).then (stats) => + return @userService.getStats(@.user.get("id")).then (stats) => @.stats = stats angular.module("taigaProfile").controller("ProfileBar", ProfileBarController) diff --git a/app/modules/profile/profile-bar/profile-bar.controller.spec.coffee b/app/modules/profile/profile-bar/profile-bar.controller.spec.coffee index 9d2b7067..f435acd0 100644 --- a/app/modules/profile/profile-bar/profile-bar.controller.spec.coffee +++ b/app/modules/profile/profile-bar/profile-bar.controller.spec.coffee @@ -1,37 +1,26 @@ describe "ProfileBar", -> $controller = null - $q = null provide = null $rootScope = null mocks = {} _mockUserService = () -> mocks.userService = { - getStats: sinon.stub() + getStats: sinon.stub().promise() } provide.value "tgUserService", mocks.userService - _mockAuthService = () -> - stub = sinon.stub() - - stub.returns({id: 2}) - - provide.value "$tgAuth", { - getUser: stub - } _mocks = () -> module ($provide) -> provide = $provide _mockUserService() - _mockAuthService() return null _inject = (callback) -> - inject (_$controller_, _$q_, _$rootScope_) -> - $q = _$q_ + inject (_$controller_, _$rootScope_) -> $rootScope = _$rootScope_ $controller = _$controller_ @@ -40,7 +29,7 @@ describe "ProfileBar", -> _mocks() _inject() - it "user stats filled", () -> + it "user stats filled", (done) -> userId = 2 stats = Immutable.fromJS([ {id: 1}, @@ -48,14 +37,15 @@ describe "ProfileBar", -> {id: 3} ]) - mocks.userService.getStats = (userId) -> - expect(userId).to.be.equal(userId) + mocks.userService.getStats.withArgs(userId).resolve(stats) - return $q (resolve, reject) -> - resolve(stats) + $scope = $rootScope.$new - ctrl = $controller("ProfileBar") + ctrl = $controller("ProfileBar", $scope, { + user: Immutable.fromJS(id: userId) + }) - $rootScope.$apply() - - expect(ctrl.stats.toJS()).to.be.eql(stats.toJS()) + setTimeout ( -> + expect(ctrl.stats.toJS()).to.be.eql(stats.toJS()) + done() + ) diff --git a/app/modules/profile/profile-bar/profile-bar.directive.coffee b/app/modules/profile/profile-bar/profile-bar.directive.coffee index a236ba61..24744b44 100644 --- a/app/modules/profile/profile-bar/profile-bar.directive.coffee +++ b/app/modules/profile/profile-bar/profile-bar.directive.coffee @@ -3,7 +3,11 @@ ProfileBarDirective = () -> templateUrl: "profile/profile-bar/profile-bar.html", controller: "ProfileBar", controllerAs: "vm", - scope: {} + scope: { + user: "=user", + isCurrentUser: "=iscurrentuser" + }, + bindToController: true } diff --git a/app/modules/profile/profile-bar/profile-bar.jade b/app/modules/profile/profile-bar/profile-bar.jade index 77f3a980..31983687 100644 --- a/app/modules/profile/profile-bar/profile-bar.jade +++ b/app/modules/profile/profile-bar/profile-bar.jade @@ -1,11 +1,11 @@ section.profile-bar - div.profile-image-wrapper - img.profile-img(ng-src="{{::vm.user.big_photo}}", alt="{{::vm.user.full_name}}") + div.profile-image-wrapper(ng-class="::{'is-current-user': vm.isCurrentUser}") + img.profile-img(ng-src="{{::vm.user.get('big_photo')}}", alt="{{::vm.user.get('full_name')}}") a.profile-edition(title="{{ 'USER.PROFILE.EDIT' | translate }}", tg-nav="user-settings-user-profile", translate="USER.PROFILE.EDIT") // a.button-green // span(translate="USER.PROFILE.FOLLOW") div.profile-data - h1 {{::vm.user.full_name}} + h1 {{::vm.user.get("full_name")}} h2 {{::vm.stats.get('roles').join(", ")}} // div.location // include ../../../svg/location.svg @@ -33,5 +33,5 @@ section.profile-bar // div.organization // div.organization - div.profile-quote(ng-if="::vm.user.bio") - span {{::vm.user.bio | limitTo:210 }}{{vm.user.bio.length < 210 ? '' : '...'}} + div.profile-quote(ng-if="::vm.user.get('bio')") + span {{::vm.user.get("bio") | limitTo:210 }}{{vm.user.get("bio").length < 210 ? '' : '...'}} diff --git a/app/modules/profile/profile-contacts/profile-contacts.controller.coffee b/app/modules/profile/profile-contacts/profile-contacts.controller.coffee index e82d8d3f..bc852e0d 100644 --- a/app/modules/profile/profile-contacts/profile-contacts.controller.coffee +++ b/app/modules/profile/profile-contacts/profile-contacts.controller.coffee @@ -1,15 +1,12 @@ class ProfileContactsController @.$inject = [ - "tgUserService", - "$tgAuth" + "tgUserService" ] - constructor: (@userService, @auth) -> + constructor: (@userService) -> loadContacts: () -> - userId = @auth.getUser().id - - @userService.getContacts(userId) + @userService.getContacts(@.userId) .then (contacts) => @.contacts = contacts diff --git a/app/modules/profile/profile-contacts/profile-contacts.controller.spec.coffee b/app/modules/profile/profile-contacts/profile-contacts.controller.spec.coffee index 2e60f51e..33c13b2a 100644 --- a/app/modules/profile/profile-contacts/profile-contacts.controller.spec.coffee +++ b/app/modules/profile/profile-contacts/profile-contacts.controller.spec.coffee @@ -1,37 +1,25 @@ describe "ProfileContacts", -> $controller = null - $q = null provide = null $rootScope = null mocks = {} _mockUserService = () -> mocks.userServices = { - getContacts: sinon.stub() + getContacts: sinon.stub().promise() } provide.value "tgUserService", mocks.userServices - _mockAuthService = () -> - stub = sinon.stub() - - stub.returns({id: 2}) - - provide.value "$tgAuth", { - getUser: stub - } - _mocks = () -> module ($provide) -> provide = $provide _mockUserService() - _mockAuthService() return null _inject = (callback) -> - inject (_$controller_, _$q_, _$rootScope_) -> - $q = _$q_ + inject (_$controller_, _$rootScope_) -> $rootScope = _$rootScope_ $controller = _$controller_ @@ -48,16 +36,14 @@ describe "ProfileContacts", -> {id: 3} ] - mocks.userServices.getContacts = (userId) -> - expect(userId).to.be.equal(userId) + mocks.userServices.getContacts.withArgs(userId).resolve(contacts) - return $q (resolve, reject) -> - resolve(contacts) + $scope = $rootScope.$new() - ctrl = $controller("ProfileContacts") + ctrl = $controller("ProfileContacts", $scope, { + userId: userId + }) ctrl.loadContacts().then () -> expect(ctrl.contacts).to.be.equal(contacts) done() - - $rootScope.$apply() diff --git a/app/modules/profile/profile-contacts/profile-contacts.directive.coffee b/app/modules/profile/profile-contacts/profile-contacts.directive.coffee index 70e2dd4d..f3398bd2 100644 --- a/app/modules/profile/profile-contacts/profile-contacts.directive.coffee +++ b/app/modules/profile/profile-contacts/profile-contacts.directive.coffee @@ -4,10 +4,13 @@ ProfileContactsDirective = () -> return { templateUrl: "profile/profile-contacts/profile-contacts.html", - scope: {}, + scope: { + userId: "=userid" + }, controllerAs: "vm", controller: "ProfileContacts", - link: link + link: link, + bindToController: true } angular.module("taigaProfile").directive("tgProfileContacts", ProfileContactsDirective) diff --git a/app/modules/profile/profile-projects/profile-projects.controller.coffee b/app/modules/profile/profile-projects/profile-projects.controller.coffee index a5c8c59c..7f15ebc7 100644 --- a/app/modules/profile/profile-projects/profile-projects.controller.coffee +++ b/app/modules/profile/profile-projects/profile-projects.controller.coffee @@ -1,18 +1,15 @@ class ProfileProjectsController @.$inject = [ "tgProjectsService", - "tgUserService", - "$tgAuth" + "tgUserService" ] - constructor: (@projectsService, @userService, @auth) -> + constructor: (@projectsService, @userService) -> loadProjects: () -> - userId = @auth.getUser().id - - @projectsService.getProjectsByUserId(userId) + @projectsService.getProjectsByUserId(@.userId) .then (projects) => - return @userService.attachUserContactsToProjects(userId, projects) + return @userService.attachUserContactsToProjects(@.userId, projects) .then (projects) => @.projects = projects diff --git a/app/modules/profile/profile-projects/profile-projects.controller.spec.coffee b/app/modules/profile/profile-projects/profile-projects.controller.spec.coffee index f9062661..44f70b6f 100644 --- a/app/modules/profile/profile-projects/profile-projects.controller.spec.coffee +++ b/app/modules/profile/profile-projects/profile-projects.controller.spec.coffee @@ -1,6 +1,5 @@ describe "ProfileProjects", -> $controller = null - $q = null provide = null $rootScope = null mocks = {} @@ -14,7 +13,7 @@ describe "ProfileProjects", -> _mockProjectsService = () -> mocks.projectsService = { - getProjectsByUserId: sinon.stub() + getProjectsByUserId: sinon.stub().promise() } provide.value "tgProjectsService", mocks.projectsService @@ -38,8 +37,7 @@ describe "ProfileProjects", -> return null _inject = (callback) -> - inject (_$controller_, _$q_, _$rootScope_) -> - $q = _$q_ + inject (_$controller_, _$rootScope_) -> $rootScope = _$rootScope_ $controller = _$controller_ @@ -62,18 +60,15 @@ describe "ProfileProjects", -> {id: 3, contacts: "fake"} ] - mocks.projectsService.getProjectsByUserId = (userId) -> - expect(userId).to.be.equal(userId) - - return $q (resolve, reject) -> - resolve(projects) - + mocks.projectsService.getProjectsByUserId.withArgs(userId).resolve(projects) mocks.userService.attachUserContactsToProjects.withArgs(userId, projects).returns(projectsWithContacts) - ctrl = $controller("ProfileProjects") + $scope = $rootScope.$new() + + ctrl = $controller("ProfileProjects", $scope, { + userId: userId + }) ctrl.loadProjects().then () -> expect(ctrl.projects).to.be.equal(projectsWithContacts) done() - - $rootScope.$apply() diff --git a/app/modules/profile/profile-projects/profile-projects.directive.coffee b/app/modules/profile/profile-projects/profile-projects.directive.coffee index 72cf4472..6a2666a7 100644 --- a/app/modules/profile/profile-projects/profile-projects.directive.coffee +++ b/app/modules/profile/profile-projects/profile-projects.directive.coffee @@ -4,7 +4,9 @@ ProfileProjectsDirective = () -> return { templateUrl: "profile/profile-projects/profile-projects.html", - scope: {}, + scope: { + userId: "=userid" + }, link: link bindToController: true, controllerAs: "vm", diff --git a/app/modules/profile/profile.controller.coffee b/app/modules/profile/profile.controller.coffee index 908de2b9..26f02f8e 100644 --- a/app/modules/profile/profile.controller.coffee +++ b/app/modules/profile/profile.controller.coffee @@ -1,16 +1,22 @@ class ProfilePageController extends taiga.Controller @.$inject = [ "$appTitle", - "$tgAuth", - "$routeParams" + "tgCurrentUserService", + "$routeParams", + "tgUserService" ] - constructor: (@appTitle, @auth, @routeParams) -> + constructor: (@appTitle, @currentUserService, @routeParams, @userService) -> if @routeParams.slug - @.user = @auth.userData + @userService + .getUserByUserName(@routeParams.slug) + .then (user) => + @.user = user + @.isCurrentUser = false + @appTitle.set(@.user.get('username')) else - @.user = @auth.userData - - @appTitle.set(@.user.get('username')) + @.user = @currentUserService.getUser() + @.isCurrentUser = true + @appTitle.set(@.user.get('username')) angular.module("taigaProfile").controller("Profile", ProfilePageController) diff --git a/app/modules/profile/profile.controller.spec.coffee b/app/modules/profile/profile.controller.spec.coffee index f054c617..f670e31a 100644 --- a/app/modules/profile/profile.controller.spec.coffee +++ b/app/modules/profile/profile.controller.spec.coffee @@ -1,7 +1,7 @@ describe "ProfileController", -> - pageCtrl = null provide = null - controller = null + $controller = null + $rootScope = null mocks = {} projects = Immutable.fromJS([ @@ -14,44 +14,89 @@ describe "ProfileController", -> stub = sinon.stub() mocks.appTitle = { - set: sinon.stub() + set: sinon.spy() } provide.value "$appTitle", mocks.appTitle - _mockAuth = () -> + _mockCurrentUser = () -> stub = sinon.stub() - mocks.auth = { - userData: Immutable.fromJS({username: "UserName"}) + mocks.currentUser = { + getUser: sinon.stub() } - provide.value "$tgAuth", mocks.auth + provide.value "tgCurrentUserService", mocks.currentUser + + _mockUserService = () -> + stub = sinon.stub() + + mocks.userService = { + getUserByUserName: sinon.stub().promise() + } + + provide.value "tgUserService", mocks.userService + + _mockRouteParams = () -> + stub = sinon.stub() + + mocks.routeParams = {} + + provide.value "$routeParams", mocks.routeParams _mocks = () -> module ($provide) -> provide = $provide _mockAppTitle() - _mockAuth() + _mockCurrentUser() + _mockRouteParams() + _mockUserService() return null + _inject = (callback) -> + inject (_$controller_, _$rootScope_) -> + $rootScope = _$rootScope_ + $controller = _$controller_ + beforeEach -> module "taigaProfile" _mocks() + _inject() - inject ($controller) -> - controller = $controller + it "define external user", (done) -> + $scope = $rootScope.$new() - it "define user", () -> - ctrl = controller "Profile", - $scope: {} + mocks.routeParams.slug = "user-slug" - expect(ctrl.user).to.be.equal(mocks.auth.userData) + ctrl = $controller("Profile") - it "define projects", () -> - ctrl = controller "Profile", - $scope: {} + user = Immutable.fromJS({ + username: "user-name" + }) - expect(mocks.appTitle.set.withArgs("UserName")).to.be.calledOnce + mocks.userService.getUserByUserName.withArgs(mocks.routeParams.slug).resolve(user) + + setTimeout ( -> + expect(ctrl.user).to.be.equal(user) + expect(ctrl.isCurrentUser).to.be.false + expect(mocks.appTitle.set.calledWithExactly("user-name")).to.be.true + + done() + ) + + it "define current user", () -> + $scope = $rootScope.$new() + + user = Immutable.fromJS({ + username: "user-name" + }) + + mocks.currentUser.getUser.returns(user) + + ctrl = $controller("Profile") + + expect(ctrl.user).to.be.equal(user) + expect(ctrl.isCurrentUser).to.be.true + expect(mocks.appTitle.set.calledWithExactly("user-name")).to.be.true diff --git a/app/modules/profile/profile.jade b/app/modules/profile/profile.jade index 6a315e06..69f49ada 100644 --- a/app/modules/profile/profile.jade +++ b/app/modules/profile/profile.jade @@ -1,16 +1,16 @@ include ../../partials/includes/components/beta -div.profile.centered - div(tg-profile-bar) +div.profile.centered(ng-if="vm.user") + div(tg-profile-bar, user="vm.user", isCurrentUser="vm.isCurrentUser") div.main 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(tg-user-timeline, userId="vm.user.get('id')") div(tg-profile-tab="projects", tab-title="{{'USER.PROFILE.PROJECTS_TAB' | translate}}", tab-icon="icon-project") - div(tg-profile-projects) + div(tg-profile-projects, userId="vm.user.get('id')") div(tg-profile-tab="contacts", tab-title="{{'USER.PROFILE.CONTACTS_TAB' | translate}}", tab-icon="icon-team") - div(tg-profile-contacts) + div(tg-profile-contacts, userId="vm.user.get('id')") // div(tg-profile-tab="favorites", tab-title="{{'USER.PROFILE.FAVORITES_TAB' | translate}}", tab-icon="icon-star-fill") // include includes/profile-favorites diff --git a/app/modules/profile/styles/profile-bar.scss b/app/modules/profile/styles/profile-bar.scss index 4149c612..abe89ca8 100644 --- a/app/modules/profile/styles/profile-bar.scss +++ b/app/modules/profile/styles/profile-bar.scss @@ -4,7 +4,7 @@ margin-bottom: 1rem; overflow: hidden; position: relative; - &:hover { + &.is-current-user:hover { img { filter: brightness(40%) saturate(150%) hue-rotate(60deg); transition: all .2s cubic-bezier(.01, .7, 1, 1); diff --git a/app/modules/resources/users-resource.service.coffee b/app/modules/resources/users-resource.service.coffee index ad7f31da..ea3e10b0 100644 --- a/app/modules/resources/users-resource.service.coffee +++ b/app/modules/resources/users-resource.service.coffee @@ -1,7 +1,22 @@ Resource = (urlsService, http) -> service = {} - service.getUserBySlug = (userSlug) -> + service.getUserByUsername = (username) -> + url = urlsService.resolve("by_username") + + httpOptions = { + headers: { + "x-disable-pagination": "1" + } + } + + params = { + username: username + } + + return http.get(url, params, httpOptions) + .then (result) -> + return Immutable.fromJS(result.data) service.getStats = (userId) -> url = urlsService.resolve("stats", userId) @@ -16,7 +31,6 @@ Resource = (urlsService, http) -> .then (result) -> return Immutable.fromJS(result.data) - service.getContacts = (userId) -> url = urlsService.resolve("contacts", userId) diff --git a/app/modules/services/user.service.coffee b/app/modules/services/user.service.coffee index 26ec4d1e..f6c803d8 100644 --- a/app/modules/services/user.service.coffee +++ b/app/modules/services/user.service.coffee @@ -5,6 +5,9 @@ class UserService extends taiga.Service constructor: (@rs) -> + getUserByUserName: (username) -> + return @rs.users.getUserByUsername(username) + getContacts: (userId) -> return @rs.users.getContacts(userId) diff --git a/app/modules/services/user.service.spec.coffee b/app/modules/services/user.service.spec.coffee index d48b0fe5..71384243 100644 --- a/app/modules/services/user.service.spec.coffee +++ b/app/modules/services/user.service.spec.coffee @@ -87,3 +87,15 @@ describe "UserService", -> done() $rootScope.$apply() + + it "get user by username", (done) -> + username = "username-1" + + user = {id: 1} + + mocks.resources.users.getUserByUsername = sinon.stub().promise() + mocks.resources.users.getUserByUsername.withArgs(username).resolve(user) + + userService.getUserByUserName(username).then (_user_) -> + expect(_user_).to.be.eql(user) + done()