user profile

stable
Juanfran 2015-05-26 12:36:45 +02:00
parent f597db104e
commit 4f0cac687d
19 changed files with 172 additions and 123 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()
)

View File

@ -3,7 +3,11 @@ ProfileBarDirective = () ->
templateUrl: "profile/profile-bar/profile-bar.html",
controller: "ProfileBar",
controllerAs: "vm",
scope: {}
scope: {
user: "=user",
isCurrentUser: "=iscurrentuser"
},
bindToController: true
}

View File

@ -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 ? '' : '...'}}

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -4,7 +4,9 @@ ProfileProjectsDirective = () ->
return {
templateUrl: "profile/profile-projects/profile-projects.html",
scope: {},
scope: {
userId: "=userid"
},
link: link
bindToController: true,
controllerAs: "vm",

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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()