Assigned Users frontend functionality
parent
cea62718b3
commit
3ec018037d
|
@ -292,7 +292,6 @@ class QueueModelTransformation extends taiga.Service
|
|||
|
||||
save: (transformation) ->
|
||||
defered = @q.defer()
|
||||
|
||||
@qqueue.add () =>
|
||||
obj = @.getObj()
|
||||
comment = obj.comment
|
||||
|
|
|
@ -230,7 +230,6 @@ WatchersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $c
|
|||
watchers = _.map(watchers, (watcherId) -> $scope.usersById[watcherId])
|
||||
renderWatchers(watchers)
|
||||
$rootscope.$broadcast("object:updated")
|
||||
|
||||
transform.then null, ->
|
||||
$confirm.notify("error")
|
||||
|
||||
|
@ -304,7 +303,7 @@ module.directive("tgWatchers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQueue
|
|||
## Assigned Users directive
|
||||
#############################################################################
|
||||
|
||||
AssignedUsersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $compile, $translate) ->
|
||||
AssignedUsersDirective = ($rootscope, $confirm, $repo, $modelTransform, $template, $compile, $translate, $currentUserService) ->
|
||||
# You have to include a div with the tg-lb-assignedusers directive in the page
|
||||
# where use this directive
|
||||
|
||||
|
@ -314,27 +313,42 @@ AssignedUsersDirective = ($rootscope, $confirm, $repo, $modelTransform, $templat
|
|||
isAssigned = ->
|
||||
return $scope.assignedUsers.length > 0
|
||||
|
||||
save = (assignedUsers) ->
|
||||
save = (assignedUsers, assignedToUser) ->
|
||||
transform = $modelTransform.save (item) ->
|
||||
item.assignedUsers = assignedUsers
|
||||
item.assigned_users = assignedUsers
|
||||
if not item.assigned_to
|
||||
item.assigned_to = assignedToUser
|
||||
return item
|
||||
|
||||
transform.then ->
|
||||
console.log(assignedUserId)
|
||||
assignedUsers = _.map(assignedUsers, (assignedUserId) -> $scope.usersById[assignedUserId])
|
||||
renderAssignedUsers(assignedUsers)
|
||||
$rootscope.$broadcast("object:updated")
|
||||
result = $rootscope.$broadcast("object:updated")
|
||||
|
||||
transform.then null, ->
|
||||
$confirm.notify("error")
|
||||
|
||||
openAssignedUsers = ->
|
||||
item = _.clone($model.$modelValue, false)
|
||||
$rootscope.$broadcast("assignedUser:add", item)
|
||||
$rootscope.$broadcast("assigned-user:add", item)
|
||||
|
||||
assignToMe = ->
|
||||
return if not isEditable()
|
||||
currentUserId = $currentUserService.getUser().get('id')
|
||||
assignedUsers = _.clone($model.$modelValue.assigned_users, false)
|
||||
assignedUsers.push(currentUserId)
|
||||
assignedUsers = _.uniq(assignedUsers)
|
||||
save(assignedUsers, currentUserId)
|
||||
|
||||
deleteAssignedUser = (assignedUserIds) ->
|
||||
transform = $modelTransform.save (item) ->
|
||||
item.assignedUsers = assignedUserIds
|
||||
item.assigned_users = assignedUserIds
|
||||
|
||||
# Update as
|
||||
if item.assigned_to not in assignedUserIds and assignedUserIds.length > 0
|
||||
item.assigned_to = assignedUserIds[0]
|
||||
if assignedUserIds.length == 0
|
||||
item.assigned_to = null
|
||||
|
||||
return item
|
||||
|
||||
|
@ -353,32 +367,32 @@ AssignedUsersDirective = ($rootscope, $confirm, $repo, $modelTransform, $templat
|
|||
$scope.isEditable = isEditable()
|
||||
$scope.isAssigned = isAssigned()
|
||||
$scope.openAssignedUsers = openAssignedUsers
|
||||
console.log('rendering...')
|
||||
$scope.assignToMe = assignToMe
|
||||
|
||||
$el.on "click", ".js-delete-watcher", (event) ->
|
||||
$el.on "click", ".remove-user", (event) ->
|
||||
event.preventDefault()
|
||||
return if not isEditable()
|
||||
target = angular.element(event.currentTarget)
|
||||
watcherId = target.data("watcher-id")
|
||||
assignedUserId = target.data("assigned-user-id")
|
||||
|
||||
title = $translate.instant("COMMON.WATCHERS.TITLE_LIGHTBOX_DELETE_WARTCHER")
|
||||
message = $scope.usersById[watcherId].full_name_display
|
||||
title = $translate.instant("COMMON.ASSIGNED_USERS.TITLE_LIGHTBOX_DELETE_ASSIGNED")
|
||||
message = $scope.usersById[assignedUserId].full_name_display
|
||||
|
||||
$confirm.askOnDelete(title, message).then (askResponse) =>
|
||||
askResponse.finish()
|
||||
|
||||
watcherIds = _.clone($model.$modelValue.watchers, false)
|
||||
watcherIds = _.pull(watcherIds, watcherId)
|
||||
assignedUserIds = _.clone($model.$modelValue.assigned_users, false)
|
||||
assignedUserIds = _.pull(assignedUserIds, assignedUserId)
|
||||
|
||||
deleteWatcher(watcherIds)
|
||||
|
||||
$scope.$on "assignedUser:added", (ctx, assignedUserId) ->
|
||||
deleteAssignedUser(assignedUserIds)
|
||||
|
||||
$scope.$on "assigned-user:added", (ctx, assignedUserId) ->
|
||||
assignedUsers = _.clone($model.$modelValue.assigned_users, false)
|
||||
assignedUsers.push(assignedUserId)
|
||||
assignedUsers = _.uniq(assignedUsers)
|
||||
|
||||
save(assignedUsers)
|
||||
# Save assigned_users and assignedUserId for assign_to legacy attribute
|
||||
save(assignedUsers, assignedUserId)
|
||||
|
||||
$scope.$watch $attrs.ngModel, (item) ->
|
||||
return if not item?
|
||||
|
@ -398,7 +412,7 @@ AssignedUsersDirective = ($rootscope, $confirm, $repo, $modelTransform, $templat
|
|||
}
|
||||
|
||||
module.directive("tgAssignedUsers", ["$rootScope", "$tgConfirm", "$tgRepo", "$tgQueueModelTransformation", "$tgTemplate", "$compile",
|
||||
"$translate", AssignedUsersDirective])
|
||||
"$translate", "tgCurrentUserService", AssignedUsersDirective])
|
||||
|
||||
|
||||
#############################################################################
|
||||
|
@ -488,7 +502,6 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $modelTransform, $
|
|||
|
||||
$scope.$on "assigned-to:added", (ctx, userId, item) ->
|
||||
return if item.id != $model.$modelValue.id
|
||||
|
||||
save(userId)
|
||||
|
||||
$scope.$watch $attrs.ngModel, (instance) ->
|
||||
|
|
|
@ -646,7 +646,6 @@ AssignedToLightboxDirective = (lightboxService, lightboxKeyboardNavigationServic
|
|||
selectedItem = item
|
||||
assignedToId = item.assigned_to
|
||||
selectedUser = $scope.usersById[assignedToId]
|
||||
|
||||
render(selectedUser)
|
||||
lightboxService.open($el).then ->
|
||||
$el.find('input').focus()
|
||||
|
@ -706,10 +705,10 @@ AssignedUsersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNaviga
|
|||
usersTemplate = $template.get("common/lightbox/lightbox-assigned-to-users.html", true)
|
||||
|
||||
# Get prefiltered users by text
|
||||
# and without now watched users.
|
||||
# and without now assigned users.
|
||||
getFilteredUsers = (text="") ->
|
||||
_filterUsers = (text, user) ->
|
||||
if selectedItem && _.find(selectedItem.assignedUsers, (x) -> x == user.id)
|
||||
if selectedItem && _.find(selectedItem.assigned_users, (x) -> x == user.id)
|
||||
return false
|
||||
|
||||
username = user.full_name_display.toUpperCase()
|
||||
|
@ -737,16 +736,14 @@ AssignedUsersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNaviga
|
|||
|
||||
html = usersTemplate(ctx)
|
||||
html = $compile(html)($scope)
|
||||
$el.find(".ticket-watchers").html(html)
|
||||
$el.find(".assigned-to-list").html(html)
|
||||
|
||||
closeLightbox = () ->
|
||||
lightboxKeyboardNavigationService.stop()
|
||||
lightboxService.close($el)
|
||||
|
||||
$scope.$on "assignedUser:add", (ctx, item) ->
|
||||
console.log(item)
|
||||
$scope.$on "assigned-user:add", (ctx, item) ->
|
||||
selectedItem = item
|
||||
|
||||
users = getFilteredUsers()
|
||||
render(users)
|
||||
|
||||
|
@ -770,7 +767,7 @@ AssignedUsersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNaviga
|
|||
|
||||
$scope.$apply ->
|
||||
$scope.usersSearch = null
|
||||
$scope.$broadcast("assignedUser:added", target.data("user-id"))
|
||||
$scope.$broadcast("assigned-user:added", target.data("user-id"), selectedItem)
|
||||
|
||||
$el.on "click", ".close", (event) ->
|
||||
event.preventDefault()
|
||||
|
@ -784,7 +781,7 @@ AssignedUsersLightboxDirective = ($repo, lightboxService, lightboxKeyboardNaviga
|
|||
$el.off()
|
||||
|
||||
return {
|
||||
templateUrl: "common/lightbox/lightbox-users.html"
|
||||
templateUrl: "common/lightbox/lightbox-assigned-users.html"
|
||||
link:link
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
|||
@kanbanUserstoriesService.replaceModel(us)
|
||||
|
||||
@scope.$on("assigned-to:added", @.onAssignedToChanged)
|
||||
@scope.$on("assigned-user:added", @.onAssignedUsersChanged)
|
||||
@scope.$on("kanban:us:move", @.moveUs)
|
||||
@scope.$on("kanban:show-userstories-for-status", @.loadUserStoriesForStatus)
|
||||
@scope.$on("kanban:hide-userstories-for-status", @.hideUserStoriesForStatus)
|
||||
|
@ -194,6 +195,10 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
|||
|
||||
@rootscope.$broadcast("assigned-to:add", us)
|
||||
|
||||
changeUsAssignedUsers: (id) ->
|
||||
us = @kanbanUserstoriesService.getUsModel(id)
|
||||
@rootscope.$broadcast("assigned-user:add", us)
|
||||
|
||||
onAssignedToChanged: (ctx, userid, usModel) ->
|
||||
usModel.assigned_to = userid
|
||||
|
||||
|
@ -204,6 +209,20 @@ class KanbanController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
|||
if @.isFilterDataTypeSelected('assigned_to') || @.isFilterDataTypeSelected('role')
|
||||
@.filtersReloadContent()
|
||||
|
||||
onAssignedUsersChanged: (ctx, userid, usModel) ->
|
||||
assignedUsers = _.clone(usModel.assigned_users, false)
|
||||
assignedUsers.push(userid)
|
||||
assignedUsers = _.uniq(assignedUsers)
|
||||
usModel.assigned_users = assignedUsers
|
||||
if not usModel.assigned_to
|
||||
usModel.assigned_to = userid
|
||||
|
||||
@kanbanUserstoriesService.replaceModel(usModel)
|
||||
|
||||
promise = @repo.save(usModel)
|
||||
promise.then null, ->
|
||||
console.log "FAIL" # TODO
|
||||
|
||||
refreshTagsColors: ->
|
||||
return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) =>
|
||||
@scope.project.tags_colors = tags_colors._attrs
|
||||
|
|
|
@ -170,6 +170,11 @@
|
|||
"PAST_DUE": "past due",
|
||||
"NO_LONGER_APPLICABLE": "no longer applicable"
|
||||
},
|
||||
"ASSIGNED_USERS": {
|
||||
"ADD": "Select assigned user",
|
||||
"ADD_ASSIGNED": "Add assigned",
|
||||
"TITLE_LIGHTBOX_DELETE_ASSIGNED": "Delete assigned..."
|
||||
},
|
||||
"STATUS": {
|
||||
"CLOSED": "Closed",
|
||||
"OPEN": "Open"
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
.assigned-title(ng-if="!isAssigned") {{ "COMMON.ASSIGNED_TO.NOT_ASSIGNED" | translate }}
|
||||
.assigned-title(ng-if="isAssigned") {{ "COMMON.FIELDS.ASSIGNED_TO" | translate }}
|
||||
|
||||
.tg-assigned-users
|
||||
.not-assigned-users(ng-if="!isAssigned")
|
||||
.user-avatar(ng-class="{'is-iocaine': isIocaine}")
|
||||
img(
|
||||
tg-avatar=""
|
||||
alt="{{ 'COMMON.ASSIGNED_TO.ASSIGN' | translate }}"
|
||||
)
|
||||
|
||||
//- .iocaine-symbol(ng-if="isIocaine" title="{{ 'TASK.TITLE_ACTION_IOCAINE' | translate }}")
|
||||
//- tg-svg(svg-icon="icon-iocaine")
|
||||
.assigned-to
|
||||
.assigned-users-options
|
||||
a(
|
||||
href=""
|
||||
title="{{ 'COMMON.ASSIGNED_TO.TITLE_ACTION_EDIT_ASSIGNMENT'|translate }}"
|
||||
class="user-assigned"
|
||||
ng-class="{editable: isEditable}"
|
||||
ng-click="openAssignedUsers()"
|
||||
)
|
||||
span.assigned-name {{ "COMMON.ASSIGNED_TO.ASSIGN" | translate }}
|
||||
|
||||
span(translate="COMMON.OR")
|
||||
|
|
||||
a.assign-to-me(
|
||||
href="#"
|
||||
title="{{'COMMON.ASSIGNED_TO.SELF' | translate}}"
|
||||
ng-click="assignToMe()"
|
||||
)
|
||||
span {{ "COMMON.ASSIGNED_TO.SELF" | translate }}
|
||||
|
||||
.user-list-single(ng-repeat="assignedUser in assignedUsers")
|
||||
.user-list-avatar
|
||||
img(
|
||||
tg-avatar="assignedUser"
|
||||
alt="{{assignedUser.full_name_display}}"
|
||||
)
|
||||
.user-list-name.assigned-users-options
|
||||
a(
|
||||
href=""
|
||||
title="{{ 'COMMON.ASSIGNED_TO.TITLE_ACTION_EDIT_ASSIGNMENT'|translate }}"
|
||||
class!="user-assigned <% if (isEditable) { %>editable<% }; %>"
|
||||
)
|
||||
span.assigned-name {{assignedUser.full_name_display}}
|
||||
tg-svg.remove-user(
|
||||
ng-if="isEditable",
|
||||
data-assigned-user-id="{{assignedUser.id}}"
|
||||
svg-icon="icon-close",
|
||||
title="{{'COMMON.ASSIGNED_TO.DELETE_ASSIGNMENT' | translate}}"
|
||||
)
|
||||
|
||||
.tg-add-assigned(ng-if="isAssigned")
|
||||
tg-svg.add-assigned(
|
||||
ng-if="isEditable",
|
||||
data-assigned-user-id="{{assignedUser.id}}",
|
||||
ng-click="openAssignedUsers()",
|
||||
svg-icon="icon-add",
|
||||
title="{{'COMMON.ASSIGNED_USERS.ADD_ASSIGNED' | translate}}"
|
||||
)
|
||||
span {{ "COMMON.ASSIGNED_USERS.ADD_ASSIGNED" | translate }}
|
|
@ -0,0 +1,8 @@
|
|||
tg-lightbox-close
|
||||
|
||||
div.form
|
||||
h2.title(translate="COMMON.ASSIGNED_USERS.ADD")
|
||||
fieldset
|
||||
input(type="text", data-maxlength="500", placeholder="{{'LIGHTBOX.ASSIGNED_TO.SEARCH' | translate}}", ng-model="usersSearch")
|
||||
div.assigned-to-list
|
||||
//- The content of this is rendered by directive
|
|
@ -80,7 +80,7 @@ div.kanban-table(
|
|||
tg-bind-scope,
|
||||
on-toggle-fold="ctrl.toggleFold(id)"
|
||||
on-click-edit="ctrl.editUs(id)"
|
||||
on-click-assigned-to="ctrl.changeUsAssignedTo(id)"
|
||||
on-click-assigned-to="ctrl.changeUsAssignedUsers(id)"
|
||||
project="project"
|
||||
item="us"
|
||||
zoom="ctrl.zoom"
|
||||
|
|
|
@ -46,4 +46,4 @@ div.wrapper(
|
|||
div.lightbox.lightbox-generic-bulk(tg-lb-create-bulk-userstories)
|
||||
include ../includes/modules/lightbox-us-bulk
|
||||
|
||||
div.lightbox.lightbox-select-user(tg-lb-assignedto)
|
||||
div.lightbox.lightbox-select-user(tg-lb-assigned-users)
|
||||
|
|
|
@ -95,6 +95,7 @@ div.wrapper(
|
|||
|
||||
tg-us-estimation.ticket-estimation(ng-model="us")
|
||||
|
||||
#TODELETE
|
||||
section.ticket-assigned-to(
|
||||
tg-assigned-to
|
||||
ng-model="us"
|
||||
|
|
|
@ -92,3 +92,35 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ticket-assigned-users {
|
||||
@include user-list;
|
||||
margin-top: 1rem;
|
||||
.user-list-single {
|
||||
flex-grow: 1;
|
||||
&:hover {
|
||||
.remove-user {
|
||||
opacity: 1;
|
||||
transition: opacity .2s ease-in;
|
||||
}
|
||||
}
|
||||
}
|
||||
.user-list-name {
|
||||
@include font-type(text);
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
.remove-user {
|
||||
cursor: pointer;
|
||||
fill: currentColor;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: .5rem;
|
||||
top: 0;
|
||||
transition: all .2s ease-in;
|
||||
&:hover {
|
||||
fill: $red;
|
||||
transition: color .3s ease-in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
.ticket-assigned-users {
|
||||
align-items: center;
|
||||
border-bottom: 1px solid $gray-light;
|
||||
border-top: 1px solid $gray-light;
|
||||
margin-bottom: 1rem;
|
||||
padding: .5rem 0;
|
||||
position: relative;
|
||||
|
||||
.loading-spinner {
|
||||
@include loading-spinner;
|
||||
margin: 1rem auto;
|
||||
max-height: 2rem;
|
||||
max-width: 2rem;
|
||||
}
|
||||
|
||||
.assigned-title {
|
||||
@include font-size(small);
|
||||
@include font-type(light);
|
||||
color: $gray;
|
||||
display: block;
|
||||
margin: .2rem 0 .25rem;
|
||||
}
|
||||
|
||||
.tg-assigned-users {
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tg-add-assigned {
|
||||
margin-top: .25rem;
|
||||
|
||||
.add-assigned {
|
||||
fill: $gray;
|
||||
opacity: 1;
|
||||
right: .5rem;
|
||||
top: 2rem;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
fill: $red;
|
||||
transition: fill .2s;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
@include font-size(small);
|
||||
@include font-type(light);
|
||||
color: $gray;
|
||||
margin: .2rem .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.assigned-users-options {
|
||||
align-content: center;
|
||||
display: flex;
|
||||
a {
|
||||
margin-right: .2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.user-assigned,
|
||||
.assign-to-me {
|
||||
color: $primary;
|
||||
&.editable {
|
||||
color: $primary;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.not-assigned-users {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
.assigned-title {
|
||||
@include font-size(small);
|
||||
@include font-type(light);
|
||||
color: $gray;
|
||||
display: block;
|
||||
margin: .2rem 0 .25rem;
|
||||
}
|
||||
.assigned-to {
|
||||
flex-grow: 1;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.assigned-to-options {
|
||||
align-content: center;
|
||||
display: flex;
|
||||
a {
|
||||
margin-right: .2rem;
|
||||
}
|
||||
}
|
||||
.user-assigned,
|
||||
.assign-to-me {
|
||||
color: $primary;
|
||||
cursor: default;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon {
|
||||
fill: currentColor;
|
||||
height: .75rem;
|
||||
width: .75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
flex-basis: 3rem;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
&.is-iocaine {
|
||||
img {
|
||||
filter: hue-rotate(150deg) saturate(200%);
|
||||
}
|
||||
}
|
||||
.iocaine-symbol {
|
||||
left: -.5rem;
|
||||
position: absolute;
|
||||
top: -.75rem;
|
||||
z-index: 9;
|
||||
svg {
|
||||
background: $grayer;
|
||||
border-radius: .25rem;
|
||||
fill: $white;
|
||||
min-height: 1.75rem;
|
||||
min-width: 1.75rem;
|
||||
padding: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue