User profile integration
parent
0c38ffc915
commit
8f5eead730
|
@ -103,12 +103,18 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide) ->
|
||||||
$routeProvider.when("/project/:pslug/user-settings/user-profile",
|
$routeProvider.when("/project/:pslug/user-settings/user-profile",
|
||||||
{templateUrl: "/partials/user-profile.html"})
|
{templateUrl: "/partials/user-profile.html"})
|
||||||
|
|
||||||
|
$routeProvider.when("/project/:pslug/user-settings/user-change-password",
|
||||||
|
{templateUrl: "/partials/user-change-password.html"})
|
||||||
|
|
||||||
$routeProvider.when("/project/:pslug/user-settings/user-avatar",
|
$routeProvider.when("/project/:pslug/user-settings/user-avatar",
|
||||||
{templateUrl: "/partials/user-avatar.html"})
|
{templateUrl: "/partials/user-avatar.html"})
|
||||||
|
|
||||||
$routeProvider.when("/project/:pslug/user-settings/mail-notifications",
|
$routeProvider.when("/project/:pslug/user-settings/mail-notifications",
|
||||||
{templateUrl: "/partials/mail-notifications.html"})
|
{templateUrl: "/partials/mail-notifications.html"})
|
||||||
|
|
||||||
|
$routeProvider.when("/change-email/:email_token",
|
||||||
|
{templateUrl: "/partials/change-email.html"})
|
||||||
|
|
||||||
# Auth
|
# Auth
|
||||||
$routeProvider.when("/login", {templateUrl: "/partials/login.html"})
|
$routeProvider.when("/login", {templateUrl: "/partials/login.html"})
|
||||||
$routeProvider.when("/register", {templateUrl: "/partials/register.html"})
|
$routeProvider.when("/register", {templateUrl: "/partials/register.html"})
|
||||||
|
|
|
@ -54,9 +54,11 @@ class AuthService extends taiga.Service
|
||||||
@rootscope.auth = user
|
@rootscope.auth = user
|
||||||
@rootscope.$broadcast("i18n:change", user.default_language)
|
@rootscope.$broadcast("i18n:change", user.default_language)
|
||||||
@storage.set("userInfo", user.getAttrs())
|
@storage.set("userInfo", user.getAttrs())
|
||||||
|
@rootscope.user = user
|
||||||
|
|
||||||
clear: ->
|
clear: ->
|
||||||
@rootscope.auth = null
|
@rootscope.auth = null
|
||||||
|
@rootscope.user = null
|
||||||
@storage.remove("userInfo")
|
@storage.remove("userInfo")
|
||||||
|
|
||||||
setToken: (token) ->
|
setToken: (token) ->
|
||||||
|
@ -93,6 +95,7 @@ class AuthService extends taiga.Service
|
||||||
|
|
||||||
logout: ->
|
logout: ->
|
||||||
@.removeToken()
|
@.removeToken()
|
||||||
|
@.clear()
|
||||||
|
|
||||||
register: (data, type, existing) ->
|
register: (data, type, existing) ->
|
||||||
url = @urls.resolve("auth-register")
|
url = @urls.resolve("auth-register")
|
||||||
|
@ -121,21 +124,19 @@ class AuthService extends taiga.Service
|
||||||
|
|
||||||
forgotPassword: (data) ->
|
forgotPassword: (data) ->
|
||||||
url = @urls.resolve("users-password-recovery")
|
url = @urls.resolve("users-password-recovery")
|
||||||
|
|
||||||
data = _.clone(data, false)
|
data = _.clone(data, false)
|
||||||
|
|
||||||
@.removeToken()
|
@.removeToken()
|
||||||
|
|
||||||
return @http.post(url, data)
|
return @http.post(url, data)
|
||||||
|
|
||||||
|
|
||||||
changePasswordFromRecovery: (data) ->
|
changePasswordFromRecovery: (data) ->
|
||||||
url = @urls.resolve("users-change-password-from-recovery")
|
url = @urls.resolve("users-change-password-from-recovery")
|
||||||
|
|
||||||
data = _.clone(data, false)
|
data = _.clone(data, false)
|
||||||
|
|
||||||
@.removeToken()
|
@.removeToken()
|
||||||
|
return @http.post(url, data)
|
||||||
|
|
||||||
|
changeEmail: (data) ->
|
||||||
|
url = @urls.resolve("users-change-email")
|
||||||
|
data = _.clone(data, false)
|
||||||
return @http.post(url, data)
|
return @http.post(url, data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -393,3 +394,44 @@ InvitationDirective = ($auth, $confirm, $location, $params) ->
|
||||||
|
|
||||||
module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$location", "$routeParams",
|
module.directive("tgInvitation", ["$tgAuth", "$tgConfirm", "$location", "$routeParams",
|
||||||
InvitationDirective])
|
InvitationDirective])
|
||||||
|
|
||||||
|
###################
|
||||||
|
## Change Email
|
||||||
|
###################
|
||||||
|
|
||||||
|
ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params) ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
$scope.data = {}
|
||||||
|
$scope.data.email_token = $params.email_token
|
||||||
|
form = $el.find("form").checksley()
|
||||||
|
|
||||||
|
onSuccessSubmit = (response) ->
|
||||||
|
$repo.queryOne("users", $auth.getUser().id).then (data) =>
|
||||||
|
$auth.setUser(data)
|
||||||
|
$location.path("/") # TODO: Use the future 'urls' service
|
||||||
|
$confirm.success("Our Oompa Loompas updated your email") #TODO: i18n
|
||||||
|
|
||||||
|
onErrorSubmit = (response) ->
|
||||||
|
console.log "ASDASDASDASD"
|
||||||
|
$confirm.notify("error", "One of our Oompa Loompas says
|
||||||
|
'#{response.data._error_message}'.") #TODO: i18n
|
||||||
|
|
||||||
|
submit = ->
|
||||||
|
if not form.validate()
|
||||||
|
return
|
||||||
|
|
||||||
|
promise = $auth.changeEmail($scope.data)
|
||||||
|
promise.then(onSuccessSubmit, onErrorSubmit)
|
||||||
|
|
||||||
|
$el.on "submit", (event) ->
|
||||||
|
event.preventDefault()
|
||||||
|
submit()
|
||||||
|
|
||||||
|
$el.on "click", "a.button-change-email", (event) ->
|
||||||
|
event.preventDefault()
|
||||||
|
submit()
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgChangeEmail", ["$tgRepo", "$tgModel", "$tgAuth", "$tgConfirm", "$location", "$routeParams",
|
||||||
|
ChangeEmailDirective])
|
||||||
|
|
|
@ -47,6 +47,7 @@ urls = {
|
||||||
"login": "/login"
|
"login": "/login"
|
||||||
"forgot-password": "/forgot-password"
|
"forgot-password": "/forgot-password"
|
||||||
"change-password": "/change-password/:token"
|
"change-password": "/change-password/:token"
|
||||||
|
"change-email": "/change-email/:token"
|
||||||
"register": "/register"
|
"register": "/register"
|
||||||
"invitation": "/invitation/:token"
|
"invitation": "/invitation/:token"
|
||||||
"create-project": "/create-project"
|
"create-project": "/create-project"
|
||||||
|
@ -91,6 +92,7 @@ urls = {
|
||||||
|
|
||||||
# User settings
|
# User settings
|
||||||
"user-settings-user-profile": "/project/:project/user-settings/user-profile"
|
"user-settings-user-profile": "/project/:project/user-settings/user-profile"
|
||||||
|
"user-settings-user-change-password": "/project/:project/user-settings/user-change-password"
|
||||||
"user-settings-user-avatar": "/project/:project/user-settings/user-avatar"
|
"user-settings-user-avatar": "/project/:project/user-settings/user-avatar"
|
||||||
"user-settings-mail-notifications": "/project/:project/user-settings/mail-notifications"
|
"user-settings-mail-notifications": "/project/:project/user-settings/mail-notifications"
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ class ConfirmService extends taiga.Service
|
||||||
@.el.off(".confirm-dialog")
|
@.el.off(".confirm-dialog")
|
||||||
delete @.el
|
delete @.el
|
||||||
|
|
||||||
ask: (title, subtitle) ->
|
ask: (title, subtitle, lightboxSelector=".lightbox_confirm-delete") ->
|
||||||
@.el = angular.element(".lightbox_confirm-delete")
|
@.el = angular.element(lightboxSelector)
|
||||||
|
|
||||||
# Render content
|
# Render content
|
||||||
@.el.find("h2.title").html(title)
|
@.el.find("h2.title").html(title)
|
||||||
|
|
|
@ -113,6 +113,9 @@ class Model
|
||||||
isModified: ->
|
isModified: ->
|
||||||
return this._isModified
|
return this._isModified
|
||||||
|
|
||||||
|
isAttributeModified: (attribute) ->
|
||||||
|
return @._modifiedAttrs[attribute]?
|
||||||
|
|
||||||
markSaved: () ->
|
markSaved: () ->
|
||||||
@._isModified = false
|
@._isModified = false
|
||||||
@._attrs = @.getAttrs()
|
@._attrs = @.getAttrs()
|
||||||
|
|
|
@ -155,12 +155,13 @@ ProjectMenuDirective = ($log, $compile, $auth, $rootscope, $tgAuth, $location) -
|
||||||
<div class="user">
|
<div class="user">
|
||||||
<div class="user-settings">
|
<div class="user-settings">
|
||||||
<ul class="popover">
|
<ul class="popover">
|
||||||
<li><a href="" title="Account settings", tg-nav="user-settings-user-profile:project=project.slug">Account settings</a></li>
|
<li><a href="" title="User Profile", tg-nav="user-settings-user-profile:project=project.slug">User Profile</a></li>
|
||||||
<li><a href="" title="Change profile photo", tg-nav="user-settings-user-avatar:project=project.slug">Change profile photo</a></li>
|
<li><a href="" title="Change Password", tg-nav="user-settings-user-change-password:project=project.slug">Change Password</a></li>
|
||||||
|
<li><a href="" title="Notifications", tg-nav="user-settings-mail-notifications:project=project.slug">Notifications</a></li>
|
||||||
<li><a href="" title="Logout" class="logout">Logout</a></li>
|
<li><a href="" title="Logout" class="logout">Logout</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<a href="" title="User preferences" class="avatar" id="nav-user-settings">
|
<a href="" title="User preferences" class="avatar" id="nav-user-settings">
|
||||||
<img src="<%- user.photo %>" alt="<%- user.full_name_display %>" />
|
<img src="{{ user.photo }}" alt="{{ user.full_name_display }}" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,6 +31,7 @@ urls = {
|
||||||
"roles": "/api/v1/roles"
|
"roles": "/api/v1/roles"
|
||||||
"projects": "/api/v1/projects"
|
"projects": "/api/v1/projects"
|
||||||
"memberships": "/api/v1/memberships"
|
"memberships": "/api/v1/memberships"
|
||||||
|
"notify-policies": "/api/v1/notify-policies"
|
||||||
"bulk-create-memberships": "/api/v1/memberships/bulk_create"
|
"bulk-create-memberships": "/api/v1/memberships/bulk_create"
|
||||||
"milestones": "/api/v1/milestones"
|
"milestones": "/api/v1/milestones"
|
||||||
"userstories": "/api/v1/userstories"
|
"userstories": "/api/v1/userstories"
|
||||||
|
@ -69,6 +70,7 @@ urls = {
|
||||||
"users-password-recovery": "/api/v1/users/password_recovery"
|
"users-password-recovery": "/api/v1/users/password_recovery"
|
||||||
"users-change-password-from-recovery": "/api/v1/users/change_password_from_recovery"
|
"users-change-password-from-recovery": "/api/v1/users/change_password_from_recovery"
|
||||||
"users-change-password": "/api/v1/users/change_password"
|
"users-change-password": "/api/v1/users/change_password"
|
||||||
|
"users-change-email": "/api/v1/users/change_email"
|
||||||
"resolver": "/api/v1/resolver"
|
"resolver": "/api/v1/resolver"
|
||||||
"userstory-statuses": "/api/v1/userstory-statuses"
|
"userstory-statuses": "/api/v1/userstory-statuses"
|
||||||
"points": "/api/v1/points"
|
"points": "/api/v1/points"
|
||||||
|
@ -115,8 +117,10 @@ module.run([
|
||||||
"$tgResources",
|
"$tgResources",
|
||||||
"$tgProjectsResourcesProvider",
|
"$tgProjectsResourcesProvider",
|
||||||
"$tgMembershipsResourcesProvider",
|
"$tgMembershipsResourcesProvider",
|
||||||
|
"$tgNotifyPoliciesResourcesProvider",
|
||||||
"$tgInvitationsResourcesProvider",
|
"$tgInvitationsResourcesProvider",
|
||||||
"$tgRolesResourcesProvider",
|
"$tgRolesResourcesProvider",
|
||||||
|
"$tgUserSettingsResourcesProvider",
|
||||||
"$tgSprintsResourcesProvider",
|
"$tgSprintsResourcesProvider",
|
||||||
"$tgUserstoriesResourcesProvider",
|
"$tgUserstoriesResourcesProvider",
|
||||||
"$tgTasksResourcesProvider",
|
"$tgTasksResourcesProvider",
|
||||||
|
|
|
@ -33,6 +33,11 @@ resourceProvider = ($repo, $http, $urls) ->
|
||||||
params = _.extend({}, params, filters or {})
|
params = _.extend({}, params, filters or {})
|
||||||
return $repo.queryPaginated("memberships", params)
|
return $repo.queryPaginated("memberships", params)
|
||||||
|
|
||||||
|
service.listByUser = (userId, filters) ->
|
||||||
|
params = {user: userId}
|
||||||
|
params = _.extend({}, params, filters or {})
|
||||||
|
return $repo.queryPaginated("memberships", params)
|
||||||
|
|
||||||
service.resendInvitation = (id) ->
|
service.resendInvitation = (id) ->
|
||||||
url = $urls.resolve("memberships")
|
url = $urls.resolve("memberships")
|
||||||
return $http.post("#{url}/#{id}/resend_invitation", {})
|
return $http.post("#{url}/#{id}/resend_invitation", {})
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: modules/resources/memberships.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
|
||||||
|
resourceProvider = ($repo, $http, $urls) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.get = (id) ->
|
||||||
|
return $repo.queryOne("notify-policies", id)
|
||||||
|
|
||||||
|
service.list = (filters) ->
|
||||||
|
params = _.extend({}, params, filters or {})
|
||||||
|
return $repo.queryMany("notify-policies", params)
|
||||||
|
|
||||||
|
return (instance) ->
|
||||||
|
instance.notifyPolicies = service
|
||||||
|
|
||||||
|
|
||||||
|
module = angular.module("taigaResources")
|
||||||
|
module.factory("$tgNotifyPoliciesResourcesProvider", ["$tgRepo", "$tgHttp", "$tgUrls", resourceProvider])
|
|
@ -0,0 +1,55 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: modules/resources/memberships.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
|
||||||
|
resourceProvider = ($repo, $http, $urls) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.changeAvatar = (attachmentModel) ->
|
||||||
|
data = new FormData()
|
||||||
|
data.append('avatar', attachmentModel)
|
||||||
|
options = {
|
||||||
|
transformRequest: angular.identity,
|
||||||
|
headers: {'Content-Type': undefined}
|
||||||
|
}
|
||||||
|
url = "#{$urls.resolve("users")}/change_avatar"
|
||||||
|
return $http.post(url, data, {}, options)
|
||||||
|
|
||||||
|
service.removeAvatar = () ->
|
||||||
|
url = "#{$urls.resolve("users")}/remove_avatar"
|
||||||
|
return $http.post(url)
|
||||||
|
|
||||||
|
service.changePassword = (currentPassword, newPassword) ->
|
||||||
|
url = "#{$urls.resolve("users")}/change_password"
|
||||||
|
data = {
|
||||||
|
current_password: currentPassword
|
||||||
|
password: newPassword
|
||||||
|
}
|
||||||
|
return $http.post(url, data)
|
||||||
|
|
||||||
|
return (instance) ->
|
||||||
|
instance.userSettings = service
|
||||||
|
|
||||||
|
|
||||||
|
module = angular.module("taigaResources")
|
||||||
|
module.factory("$tgUserSettingsResourcesProvider", ["$tgRepo", "$tgHttp", "$tgUrls", resourceProvider])
|
|
@ -0,0 +1,93 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: modules/user-settings/main.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
|
||||||
|
mixOf = @.taiga.mixOf
|
||||||
|
|
||||||
|
module = angular.module("taigaUserSettings")
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User ChangePassword Controller
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
class UserChangePasswordController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
|
@.$inject = [
|
||||||
|
"$scope",
|
||||||
|
"$rootScope",
|
||||||
|
"$tgRepo",
|
||||||
|
"$tgConfirm",
|
||||||
|
"$tgResources",
|
||||||
|
"$routeParams",
|
||||||
|
"$q",
|
||||||
|
"$location",
|
||||||
|
"$tgAuth"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @auth) ->
|
||||||
|
@scope.sectionName = "Change Password" #i18n
|
||||||
|
@scope.project = {}
|
||||||
|
@scope.user = @auth.getUser()
|
||||||
|
|
||||||
|
promise = @.loadInitialData()
|
||||||
|
promise.then null, ->
|
||||||
|
console.log "FAIL" #TODO
|
||||||
|
|
||||||
|
loadProject: ->
|
||||||
|
return @rs.projects.get(@scope.projectId).then (project) =>
|
||||||
|
@scope.project = project
|
||||||
|
return project
|
||||||
|
|
||||||
|
loadInitialData: ->
|
||||||
|
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
||||||
|
@scope.projectId = data.project
|
||||||
|
return data
|
||||||
|
|
||||||
|
return promise.then(=> @.loadProject())
|
||||||
|
|
||||||
|
save: ->
|
||||||
|
if @scope.newPassword1 != @scope.newPassword2
|
||||||
|
@confirm.notify('error', "The passwords dosn't match")
|
||||||
|
return
|
||||||
|
|
||||||
|
promise = @rs.userSettings.changePassword(@scope.currentPassword, @scope.newPassword1)
|
||||||
|
promise.then =>
|
||||||
|
@confirm.notify('success')
|
||||||
|
promise.then null, (response) =>
|
||||||
|
@confirm.notify('error', response.data._error_message)
|
||||||
|
|
||||||
|
|
||||||
|
module.controller("UserChangePasswordController", UserChangePasswordController)
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User ChangePassword Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
UserChangePasswordDirective = () ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgUserChangePassword", UserChangePasswordDirective)
|
|
@ -0,0 +1,66 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: modules/issues/lightboxes.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
bindOnce = @.taiga.bindOnce
|
||||||
|
|
||||||
|
module = angular.module("taigaUserSettings")
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## Delete User Lightbox Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
DeleteUserDirective = ($repo, $rootscope, $auth, $location) ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
$scope.$on "deletelightbox:new", (ctx, user)->
|
||||||
|
$el.removeClass("hidden")
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
|
submit = ->
|
||||||
|
promise = $repo.remove($scope.user)
|
||||||
|
|
||||||
|
promise.then (data) ->
|
||||||
|
$el.addClass("hidden")
|
||||||
|
$auth.logout()
|
||||||
|
$location.path("/login")
|
||||||
|
|
||||||
|
# FIXME: error handling?
|
||||||
|
promise.then null, ->
|
||||||
|
console.log "FAIL"
|
||||||
|
|
||||||
|
$el.on "click", ".close", (event) ->
|
||||||
|
event.preventDefault()
|
||||||
|
$el.addClass("hidden")
|
||||||
|
|
||||||
|
$el.on "click", ".button-red", (event) ->
|
||||||
|
event.preventDefault()
|
||||||
|
$el.addClass("hidden")
|
||||||
|
|
||||||
|
$el.on "click", ".button-green", (event) ->
|
||||||
|
event.preventDefault()
|
||||||
|
submit()
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
|
||||||
|
module.directive("tgLbDeleteUser", ["$tgRepo", "$rootScope", "$tgAuth", "$location", DeleteUserDirective])
|
|
@ -65,6 +65,27 @@ class UserSettingsController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
|
|
||||||
return promise.then(=> @.loadProject())
|
return promise.then(=> @.loadProject())
|
||||||
|
|
||||||
|
saveUserProfile: ->
|
||||||
|
|
||||||
|
updatingEmail = @scope.user.isAttributeModified("email")
|
||||||
|
promise = @repo.save(@scope.user)
|
||||||
|
promise.then =>
|
||||||
|
@auth.setUser(@scope.user)
|
||||||
|
if updatingEmail
|
||||||
|
@confirm.success("<strong>Check your inbox!</strong><br />
|
||||||
|
We have sent a mail to your account<br />
|
||||||
|
with the instructions to set your new address") #TODO: i18n
|
||||||
|
|
||||||
|
else
|
||||||
|
@confirm.notify('success')
|
||||||
|
|
||||||
|
promise.then null, (response) =>
|
||||||
|
@confirm.notify('error', response._error_message)
|
||||||
|
@scope.user = @auth.getUser()
|
||||||
|
|
||||||
|
openDeleteLightbox: ->
|
||||||
|
@rootscope.$broadcast("deletelightbox:new", @scope.user)
|
||||||
|
|
||||||
|
|
||||||
module.controller("UserSettingsController", UserSettingsController)
|
module.controller("UserSettingsController", UserSettingsController)
|
||||||
|
|
||||||
|
@ -74,6 +95,13 @@ module.controller("UserSettingsController", UserSettingsController)
|
||||||
|
|
||||||
UserProfileDirective = () ->
|
UserProfileDirective = () ->
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
form = $el.find("form").checksley()
|
||||||
|
|
||||||
|
$el.on "click", ".user-profile form .save-profile", (event) ->
|
||||||
|
return if not form.validate()
|
||||||
|
target = angular.element(event.currentTarget)
|
||||||
|
$ctrl = $el.controller()
|
||||||
|
$ctrl.saveUserProfile()
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
@ -81,3 +109,52 @@ UserProfileDirective = () ->
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgUserProfile", UserProfileDirective)
|
module.directive("tgUserProfile", UserProfileDirective)
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User Avatar Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
UserAvatarDirective = ($auth, $model, $rs, $confirm) ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
|
$el.on "click", ".button.change", ->
|
||||||
|
$el.find("#avatar-field").click()
|
||||||
|
|
||||||
|
$el.on "change", "#avatar-field", (event) ->
|
||||||
|
target = angular.element(event.currentTarget)
|
||||||
|
|
||||||
|
promise = $rs.userSettings.changeAvatar($scope.avatarAttachment)
|
||||||
|
|
||||||
|
promise.then (response) ->
|
||||||
|
user = $model.make_model("users", response.data)
|
||||||
|
$auth.setUser(user)
|
||||||
|
$scope.user = user
|
||||||
|
$confirm.notify('success')
|
||||||
|
promise.then null, (response) ->
|
||||||
|
console.log response
|
||||||
|
$confirm.notify('error', response.data._error_message)
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgUserAvatar", ["$tgAuth", "$tgModel", "$tgResources", "$tgConfirm", UserAvatarDirective])
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User Avatar Model Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
TaigaAvatarModelDirective = ($parse) ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
model = $parse($attrs.tgAvatarModel)
|
||||||
|
modelSetter = model.assign
|
||||||
|
|
||||||
|
$el.bind 'change', ->
|
||||||
|
$scope.$apply ->
|
||||||
|
modelSetter($scope, $el[0].files[0])
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive('tgAvatarModel', ['$parse', TaigaAvatarModelDirective])
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||||
|
# Copyright (C) 2014 Jesús Espino Garcia <jespinog@gmail.com>
|
||||||
|
# Copyright (C) 2014 David Barragán Merino <bameda@dbarragan.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# File: modules/user-settings/main.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
|
||||||
|
mixOf = @.taiga.mixOf
|
||||||
|
bindOnce = @.taiga.bindOnce
|
||||||
|
|
||||||
|
module = angular.module("taigaUserSettings")
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User settings Controller
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
class UserNotificationsController extends mixOf(taiga.Controller, taiga.PageMixin)
|
||||||
|
@.$inject = [
|
||||||
|
"$scope",
|
||||||
|
"$rootScope",
|
||||||
|
"$tgRepo",
|
||||||
|
"$tgConfirm",
|
||||||
|
"$tgResources",
|
||||||
|
"$routeParams",
|
||||||
|
"$q",
|
||||||
|
"$location",
|
||||||
|
"$tgAuth"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @auth) ->
|
||||||
|
@scope.sectionName = "Email Notifications" #i18n
|
||||||
|
@scope.project = {}
|
||||||
|
@scope.user = @auth.getUser()
|
||||||
|
|
||||||
|
promise = @.loadInitialData()
|
||||||
|
promise.then null, ->
|
||||||
|
console.log "FAIL" #TODO
|
||||||
|
|
||||||
|
loadProject: ->
|
||||||
|
return @rs.projects.get(@scope.projectId).then (project) =>
|
||||||
|
@scope.project = project
|
||||||
|
return project
|
||||||
|
|
||||||
|
loadNotifyPolicies: ->
|
||||||
|
return @rs.notifyPolicies.list().then (notifyPolicies) =>
|
||||||
|
@scope.notifyPolicies = notifyPolicies
|
||||||
|
return notifyPolicies
|
||||||
|
|
||||||
|
loadInitialData: ->
|
||||||
|
promise = @repo.resolve({pslug: @params.pslug}).then (data) =>
|
||||||
|
@scope.projectId = data.project
|
||||||
|
return data
|
||||||
|
|
||||||
|
return promise.then(=> @.loadProject())
|
||||||
|
.then(=> @.loadNotifyPolicies())
|
||||||
|
|
||||||
|
|
||||||
|
module.controller("UserNotificationsController", UserNotificationsController)
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User Notifications Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
UserNotificationsDirective = () ->
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgUserNotifications", UserNotificationsDirective)
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User Notifications List Directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
UserNotificationsListDirective = ($repo, $confirm) ->
|
||||||
|
template = _.template("""
|
||||||
|
<% _.each(notifyPolicies, function (notifyPolicy, index) { %>
|
||||||
|
<div class="policy-table-row" data-index="<%- index %>">
|
||||||
|
<div class="policy-table-project"><span><%- notifyPolicy.project_name %></span></div>
|
||||||
|
<div class="policy-table-all">
|
||||||
|
<fieldset>
|
||||||
|
<input type="radio"
|
||||||
|
name="policy-<%- notifyPolicy.id %>" id="policy-all-<%- notifyPolicy.id %>"
|
||||||
|
value="2" <% if (notifyPolicy.notify_level == 2) { %>checked="checked"<% } %>/>
|
||||||
|
<label for="policy-all-<%- notifyPolicy.id %>">All</label>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<div class="policy-table-involved">
|
||||||
|
<fieldset>
|
||||||
|
<input type="radio"
|
||||||
|
name="policy-<%- notifyPolicy.id %>" id="policy-involved-<%- notifyPolicy.id %>"
|
||||||
|
value="1" <% if (notifyPolicy.notify_level == 1) { %>checked="checked"<% } %> />
|
||||||
|
<label for="policy-involved-<%- notifyPolicy.id %>">Involved</label>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
<div class="policy-table-none">
|
||||||
|
<fieldset>
|
||||||
|
<input type="radio"
|
||||||
|
name="policy-<%- notifyPolicy.id %>" id="policy-none-<%- notifyPolicy.id %>"
|
||||||
|
value="3" <% if (notifyPolicy.notify_level == 3) { %>checked="checked"<% } %> />
|
||||||
|
<label for="policy-none-<%- notifyPolicy.id %>">None</label>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% }) %>
|
||||||
|
""")
|
||||||
|
link = ($scope, $el, $attrs) ->
|
||||||
|
|
||||||
|
render = ->
|
||||||
|
$el.off()
|
||||||
|
$el.html(template({notifyPolicies: $scope.notifyPolicies}))
|
||||||
|
$el.on "change", "input[type=radio]", (event) ->
|
||||||
|
target = angular.element(event.currentTarget)
|
||||||
|
policyIndex = target.parents(".policy-table-row").data('index')
|
||||||
|
policy = $scope.notifyPolicies[policyIndex]
|
||||||
|
|
||||||
|
prev_level = policy.notify_level
|
||||||
|
policy.notify_level = parseInt(target.val(), 10)
|
||||||
|
|
||||||
|
$repo.save(policy).then ->
|
||||||
|
$repo.save(policy).then null, ->
|
||||||
|
$confirm.notify("error")
|
||||||
|
target.parents(".policy-table-row").find("input[value=#{prev_level}]").prop("checked", true)
|
||||||
|
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
|
|
||||||
|
bindOnce($scope, $attrs.ngModel, render)
|
||||||
|
|
||||||
|
return {link:link}
|
||||||
|
|
||||||
|
module.directive("tgUserNotificationsList", ["$tgRepo", "$tgConfirm", UserNotificationsListDirective])
|
|
@ -0,0 +1,14 @@
|
||||||
|
extends dummy-layout
|
||||||
|
|
||||||
|
block head
|
||||||
|
title Taiga Project management web application with scrum in mind!
|
||||||
|
|
||||||
|
block content
|
||||||
|
div.wrapper
|
||||||
|
div.login-main
|
||||||
|
div.login-container
|
||||||
|
h1.logo
|
||||||
|
img(src="/images/logo.png", alt="TAIGA")
|
||||||
|
p.tagline Project management web application with scrum in mind!
|
||||||
|
|
||||||
|
include views/modules/change-email-form
|
|
@ -4,14 +4,15 @@ block head
|
||||||
title Taiga Project management web application with scrum in mind!
|
title Taiga Project management web application with scrum in mind!
|
||||||
|
|
||||||
block content
|
block content
|
||||||
div.wrapper(tg-user-profile, ng-controller="UserSettingsController as ctrl",
|
div.wrapper(tg-user-notifications, ng-controller="UserNotificationsController as ctrl",
|
||||||
ng-init="section='mail-notifications'")
|
ng-init="section='mail-notifications'")
|
||||||
sidebar.menu-secondary.sidebar(tg-user-settings-navigation="mail-notifications")
|
sidebar.menu-secondary.sidebar(tg-user-settings-navigation="mail-notifications")
|
||||||
include views/modules/user-settings-menu
|
include views/modules/user-settings-menu
|
||||||
|
|
||||||
section.main.admin-roles
|
section.main.admin-roles
|
||||||
header
|
header
|
||||||
include views/components/mainTitle
|
h1
|
||||||
|
span.green(tg-bo-html="sectionName")
|
||||||
|
|
||||||
p.total Notifications By Mail
|
p.total Notifications By Mail
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
extends dummy-layout
|
|
||||||
|
|
||||||
block head
|
|
||||||
title Taiga Project management web application with scrum in mind!
|
|
||||||
|
|
||||||
block content
|
|
||||||
div.wrapper(tg-user-avatar, ng-controller="UserSettingsController as ctrl",
|
|
||||||
ng-init="section='user-settings'")
|
|
||||||
sidebar.menu-secondary.sidebar(tg-user-settings-navigation="avatar")
|
|
||||||
include views/modules/user-settings-menu
|
|
||||||
|
|
||||||
section.main.user-avatar
|
|
||||||
header
|
|
||||||
include views/components/mainTitle
|
|
||||||
|
|
||||||
form
|
|
||||||
fieldset
|
|
||||||
img.avatar(tg-bo-src="user.photo" alt="avatar")
|
|
||||||
a.button.button-green Cambiar
|
|
||||||
input(type="file", id="user-avatar", ng-value="user.photo", class="hidden")
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
extends dummy-layout
|
||||||
|
|
||||||
|
block head
|
||||||
|
title Taiga Project management web application with scrum in mind!
|
||||||
|
|
||||||
|
block content
|
||||||
|
div.wrapper(tg-user-change-password, ng-controller="UserChangePasswordController as ctrl",
|
||||||
|
ng-init="section='user-settings'")
|
||||||
|
sidebar.menu-secondary.sidebar(tg-user-settings-navigation="change-password")
|
||||||
|
include views/modules/user-settings-menu
|
||||||
|
|
||||||
|
section.main.user-change-password
|
||||||
|
header
|
||||||
|
h1
|
||||||
|
span.green(tg-bo-html="sectionName")
|
||||||
|
|
||||||
|
form
|
||||||
|
fieldset
|
||||||
|
label(for="current-password") Current Password
|
||||||
|
input(type="password", placeholder="Password", id="current-password", ng-model="currentPassword")
|
||||||
|
fieldset
|
||||||
|
label(for="new-password") New Password
|
||||||
|
input(type="password", placeholder="New Password", id="new-password", ng-model="newPassword1")
|
||||||
|
fieldset
|
||||||
|
label(for="retype-password") Retype Password
|
||||||
|
input(type="password", placeholder="Retype Password", id="retype-password", ng-model="newPassword2")
|
||||||
|
fieldset
|
||||||
|
input(type="submit", class="hidden")
|
||||||
|
a.button.button-green(href="", ng-click="ctrl.save()") Save
|
||||||
|
|
||||||
|
div.lightbox.lightbox-delete-account.hidden
|
||||||
|
include views/modules/lightbox-delete-account
|
|
@ -11,25 +11,36 @@ block content
|
||||||
|
|
||||||
section.main.user-profile
|
section.main.user-profile
|
||||||
header
|
header
|
||||||
include views/components/mainTitle
|
h1
|
||||||
|
span.green(tg-bo-html="sectionName")
|
||||||
|
|
||||||
form
|
form
|
||||||
fieldset
|
fieldset.avatar(tg-user-avatar)
|
||||||
label(for="user-email") Email
|
img.avatar(ng-src="{{user.big_photo}}" alt="avatar")
|
||||||
input(type="text", placeholder="Email", id="user-email", ng-value="user.email")
|
input(type="file", id="avatar-field", tg-avatar-model="avatarAttachment" class="hidden")
|
||||||
fieldset
|
p The image will be cropped to 80x80 size.
|
||||||
label(for="current-password") Current Password
|
a.button.button-green.change Cambiar
|
||||||
input(type="password", placeholder="Password", id="current-password")
|
a.use-gravatar Use gravatar image
|
||||||
fieldset
|
|
||||||
label(for="new-password") New Password
|
|
||||||
input(type="password", placeholder="New Password", id="new-password")
|
|
||||||
fieldset
|
|
||||||
label(for="retype-password") Retype Password
|
|
||||||
input(type="password", placeholder="Retype Password", id="retype-password")
|
|
||||||
fieldset
|
|
||||||
input(type="submit", class="hidden")
|
|
||||||
a.button.button-green(href="") Save
|
|
||||||
a.delete-account(href="", title="Delete Taiga account") Delete Taiga account
|
|
||||||
|
|
||||||
div.lightbox.lightbox-delete-account.hidden
|
fieldset
|
||||||
|
label(for="email") Email
|
||||||
|
input(type="text", placeholder="email", id="email", ng-model="user.email", data-type="email")
|
||||||
|
|
||||||
|
fieldset
|
||||||
|
label(for="name") Name
|
||||||
|
input(type="text", placeholder="Name", id="name", ng-model="user.full_name")
|
||||||
|
|
||||||
|
fieldset
|
||||||
|
label(for="bio") Bio
|
||||||
|
textarea(placeholder="Bio", id="bio", ng-model="user.bio")
|
||||||
|
|
||||||
|
fieldset.submit
|
||||||
|
input(type="submit", class="hidden")
|
||||||
|
a.button.button-green.save-profile(href="") Save
|
||||||
|
a.delete-account(href="", title="Delete Taiga account", ng-click="ctrl.openDeleteLightbox()") Delete Taiga account
|
||||||
|
|
||||||
|
div.lightbox.lightbox-delete-account.hidden(tg-lb-delete-user)
|
||||||
include views/modules/lightbox-delete-account
|
include views/modules/lightbox-delete-account
|
||||||
|
|
||||||
|
div.lightbox.lightbox_confirm-use-gravatar.hidden
|
||||||
|
include views/modules/lightbox-use-gravatar
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
div.change-email-form-container(tg-change-email)
|
||||||
|
p.change-password-text
|
||||||
|
strong Change your email <br />
|
||||||
|
span One click more and your email will be updated!
|
||||||
|
|
||||||
|
form(ng-submit="ctrl.submit()")
|
||||||
|
fieldset
|
||||||
|
input(type="hidden", name="email_token", ng-model="data.email_token", data-required="true",
|
||||||
|
placeholder="change email token")
|
||||||
|
|
||||||
|
a.button.button-change-email.button-gray(href="", title="Change email") Change email
|
||||||
|
input(type="submit", style="display:none")
|
|
@ -0,0 +1,11 @@
|
||||||
|
a.close(href="", title="close")
|
||||||
|
span.icon.icon-delete
|
||||||
|
form
|
||||||
|
h2.title Use gravatar as image
|
||||||
|
p
|
||||||
|
span.subtitle You really want to delete your current photo and use the gravatar image?
|
||||||
|
div.options
|
||||||
|
a.button.button-green(href="", title="Accept")
|
||||||
|
span Accept
|
||||||
|
a.button.button-red(href="", title="Delete")
|
||||||
|
span Cancel
|
|
@ -8,9 +8,9 @@ section.admin-menu
|
||||||
a(href="", tg-nav="user-settings-user-profile:project=project.slug")
|
a(href="", tg-nav="user-settings-user-profile:project=project.slug")
|
||||||
span.title User profile
|
span.title User profile
|
||||||
span.icon.icon-arrow-right
|
span.icon.icon-arrow-right
|
||||||
li#usersettingsmenu-avatar
|
li#usersettingsmenu-change-password
|
||||||
a(href="" tg-nav="user-settings-user-avatar:project=project.slug")
|
a(href="" tg-nav="user-settings-user-change-password:project=project.slug")
|
||||||
span.title User avatar
|
span.title Change password
|
||||||
span.icon.icon-arrow-right
|
span.icon.icon-arrow-right
|
||||||
li#usersettingsmenu-mail-notifications
|
li#usersettingsmenu-mail-notifications
|
||||||
a(href="", tg-nav="user-settings-mail-notifications:project=project.slug")
|
a(href="", tg-nav="user-settings-mail-notifications:project=project.slug")
|
||||||
|
|
|
@ -1,27 +1,12 @@
|
||||||
section.mail-notifications-table
|
section.policy-table
|
||||||
div.mail-notifications-table-header
|
div.policy-table-header
|
||||||
div.mail-notifications-table-row
|
div.policy-table-row
|
||||||
div.mail-notifications-table-project
|
div.policy-table-project
|
||||||
span Project
|
span Project
|
||||||
div.mail-notifications-table-all
|
div.policy-table-all
|
||||||
span Receive All
|
span Receive All
|
||||||
div.mail-notifications-table-involved
|
div.policy-table-involved
|
||||||
span Only Involved
|
span Only Involved
|
||||||
div.mail-notifications-table-none
|
div.policy-table-none
|
||||||
span No notifications
|
span No notifications
|
||||||
div.mail-notifications-table-body
|
div.policy-table-body(tg-user-notifications-list, ng-model="notifyPolicies")
|
||||||
div.mail-notifications-table-row
|
|
||||||
div.mail-notifications-table-project
|
|
||||||
span Decathlon
|
|
||||||
div.mail-notifications-table-all
|
|
||||||
fieldset
|
|
||||||
input(type="radio", name="mail-notifications", id="notifications-all")
|
|
||||||
label(for="notifications-all") All
|
|
||||||
div.mail-notifications-table-involved
|
|
||||||
fieldset
|
|
||||||
input(type="radio", name="mail-notifications", id="notifications-involved")
|
|
||||||
label(for="notifications-involved") Involved
|
|
||||||
div.mail-notifications-table-none
|
|
||||||
fieldset
|
|
||||||
input(type="radio", name="mail-notifications", id="notifications-none")
|
|
||||||
label(for="notifications-none") None
|
|
||||||
|
|
|
@ -105,9 +105,9 @@ $prefix-for-spec: true;
|
||||||
@import 'modules/admin/project-values';
|
@import 'modules/admin/project-values';
|
||||||
|
|
||||||
//Modules user Settings
|
//Modules user Settings
|
||||||
@import 'modules/user-settings/mail-notifications-table';
|
|
||||||
@import 'modules/user-settings/user-profile';
|
@import 'modules/user-settings/user-profile';
|
||||||
@import 'modules/user-settings/user-avatar';
|
@import 'modules/user-settings/user-change-password';
|
||||||
|
@import 'modules/user-settings/mail-notifications-table';
|
||||||
|
|
||||||
//#################################################
|
//#################################################
|
||||||
// Layout
|
// Layout
|
||||||
|
|
|
@ -261,6 +261,33 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lightbox_confirm-use-gravatar {
|
||||||
|
form {
|
||||||
|
@include table-flex-child(0, 420px, 0, 420px);
|
||||||
|
}
|
||||||
|
.delete-question,
|
||||||
|
.subtitle {
|
||||||
|
display: block;
|
||||||
|
line-height: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
@extend %large;
|
||||||
|
@extend %title;
|
||||||
|
}
|
||||||
|
.options {
|
||||||
|
@include table-flex();
|
||||||
|
a {
|
||||||
|
@include table-flex-child(1, 0, 0);
|
||||||
|
padding: 8px 0;
|
||||||
|
text-align: center;
|
||||||
|
&:first-child {
|
||||||
|
margin-right: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.lightbox-delete-account {
|
.lightbox-delete-account {
|
||||||
form {
|
form {
|
||||||
@include table-flex-child(0, 420px, 0, 420px);
|
@include table-flex-child(0, 420px, 0, 420px);
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
.mail-notifications-table {
|
.policy-table {
|
||||||
.mail-notifications-table-row {
|
.policy-table-row {
|
||||||
@include table-flex(stretch, center, flex, row, wrap, center);
|
@include table-flex(stretch, center, flex, row, wrap, center);
|
||||||
border-bottom: 1px solid $whitish;
|
border-bottom: 1px solid $whitish;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mail-notifications-table-header {
|
.policy-table-header {
|
||||||
@extend %bold;
|
@extend %bold;
|
||||||
border-bottom: 2px solid $gray-light;
|
border-bottom: 2px solid $gray-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mail-notifications-table-project ,
|
.policy-table-project ,
|
||||||
.mail-notifications-table-all,
|
.policy-table-all,
|
||||||
.mail-notifications-table-involved,
|
.policy-table-involved,
|
||||||
.mail-notifications-table-none {
|
.policy-table-none {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mail-notifications-table-project {
|
.policy-table-project {
|
||||||
@include table-flex-child(3, 0, 0);
|
@include table-flex-child(3, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mail-notifications-table-all,
|
.policy-table-all,
|
||||||
.mail-notifications-table-involved,
|
.policy-table-involved,
|
||||||
.mail-notifications-table-none {
|
.policy-table-none {
|
||||||
@include table-flex-child(1, 0, 0);
|
@include table-flex-child(1, 0, 0);
|
||||||
}
|
}
|
||||||
input {
|
input {
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
.user-avatar {
|
|
||||||
fieldset {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
width: 50%;
|
|
||||||
&:last-child {
|
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
border: 2px solid $white;
|
|
||||||
border-radius: 8%;
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
.button {
|
|
||||||
bottom: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
height: 34px;
|
|
||||||
left: 85px;
|
|
||||||
position: absolute;
|
|
||||||
width: 130px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
.user-change-password {
|
||||||
|
fieldset {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
width: 50%;
|
||||||
|
&:last-child {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
@extend %title;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
.button-green {
|
||||||
|
color: $white;
|
||||||
|
display: block;
|
||||||
|
padding: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,43 @@
|
||||||
.user-profile {
|
.user-profile {
|
||||||
input[type="text"],
|
|
||||||
input[type="email"] {
|
|
||||||
@extend %title;
|
|
||||||
background-color: $very-light-gray;
|
|
||||||
}
|
|
||||||
fieldset {
|
fieldset {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
width: 50%;
|
width: 37%;
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
&.avatar {
|
||||||
|
float: left;
|
||||||
|
margin: 0 1% 0 0;
|
||||||
|
width: 12%;
|
||||||
|
img {
|
||||||
|
border: 2px solid $white;
|
||||||
|
border-radius: 8%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
@extend %xsmall;
|
||||||
|
margin-bottom: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
bottom: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
height: 34px;
|
||||||
|
margin: 5px 10%;
|
||||||
|
padding: 7px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
.use-gravatar {
|
||||||
|
@extend %small;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.submit {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
@extend %title;
|
@extend %title;
|
||||||
|
|
Loading…
Reference in New Issue