Refactoring estimation points selector
parent
6a5641c06b
commit
2a682057ac
|
@ -733,7 +733,6 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
|
||||||
$el.on "click", ".role", (event) ->
|
$el.on "click", ".role", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
rolScope = target.scope()
|
rolScope = target.scope()
|
||||||
$rootscope.$broadcast("uspoints:select", target.data("role-id"), target.text())
|
$rootscope.$broadcast("uspoints:select", target.data("role-id"), target.text())
|
||||||
|
@ -746,170 +745,107 @@ UsRolePointsSelectorDirective = ($rootscope, $template) ->
|
||||||
module.directive("tgUsRolePointsSelector", ["$rootScope", "$tgTemplate", UsRolePointsSelectorDirective])
|
module.directive("tgUsRolePointsSelector", ["$rootScope", "$tgTemplate", UsRolePointsSelectorDirective])
|
||||||
|
|
||||||
|
|
||||||
UsPointsDirective = ($repo, $tgTemplate) ->
|
UsPointsDirective = ($tgEstimationsService, $repo, $tgTemplate) ->
|
||||||
rolesTemplate = $tgTemplate.get("common/estimation/us-points-roles-popover.html", true)
|
rolesTemplate = $tgTemplate.get("common/estimation/us-points-roles-popover.html", true)
|
||||||
pointsTemplate = $tgTemplate.get("common/estimation/us-estimation-points.html", true)
|
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$ctrl = $el.controller()
|
$ctrl = $el.controller()
|
||||||
|
|
||||||
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
|
||||||
|
|
||||||
updatingSelectedRoleId = null
|
updatingSelectedRoleId = null
|
||||||
selectedRoleId = null
|
selectedRoleId = null
|
||||||
numberOfRoles = _.size(us.points)
|
filteringRoleId = null
|
||||||
|
estimationProcess = null
|
||||||
|
|
||||||
# Preselect the role if we have only one
|
$scope.$on "uspoints:select", (ctx, roleId, roleName) ->
|
||||||
if numberOfRoles == 1
|
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
||||||
selectedRoleId = _.keys(us.points)[0]
|
selectedRoleId = roleId
|
||||||
|
estimationProcess.render()
|
||||||
|
|
||||||
roles = []
|
$scope.$on "uspoints:clear-selection", (ctx) ->
|
||||||
updatePointsRoles = ->
|
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
||||||
roles = _.map computableRoles, (role) ->
|
selectedRoleId = null
|
||||||
pointId = us.points[role.id]
|
estimationProcess.render()
|
||||||
pointObj = $scope.pointsById[pointId]
|
|
||||||
|
|
||||||
role = _.clone(role, true)
|
$scope.$watch $attrs.tgBacklogUsPoints, (us) ->
|
||||||
role.points = if pointObj.value? then pointObj.value else "?"
|
if us
|
||||||
return role
|
estimationProcess = $tgEstimationsService.create($el, us, $scope.project)
|
||||||
|
|
||||||
computableRoles = _.filter($scope.project.roles, "computable")
|
# Update roles
|
||||||
updatePointsRoles()
|
roles = estimationProcess.calculateRoles()
|
||||||
|
if roles.length == 0
|
||||||
|
$el.find(".icon-arrow-bottom").remove()
|
||||||
|
$el.find("a.us-points").addClass("not-clickable")
|
||||||
|
|
||||||
if roles.length == 0
|
else if roles.length == 1
|
||||||
$el.find(".icon-arrow-bottom").remove()
|
# Preselect the role if we have only one
|
||||||
$el.find("a.us-points").addClass("not-clickable")
|
selectedRoleId = _.keys(us.points)[0]
|
||||||
|
|
||||||
renderPointsSelector = (us, roleId) ->
|
if estimationProcess.isEditable
|
||||||
# Prepare data for rendering
|
bindClickElements()
|
||||||
points = _.map $scope.project.points, (point) ->
|
|
||||||
point = _.clone(point, true)
|
|
||||||
point.selected = if us.points[roleId] == point.id then false else true
|
|
||||||
return point
|
|
||||||
|
|
||||||
html = pointsTemplate({"points": points, "roleId": roleId})
|
estimationProcess.onSelectedPointForRole = (roleId, pointId) ->
|
||||||
|
@save(roleId, pointId).then ->
|
||||||
|
$ctrl.loadProjectStats()
|
||||||
|
|
||||||
# Remove any prevous state
|
estimationProcess.render = () ->
|
||||||
$el.find(".popover").popover().close()
|
totalPoints = @calculateTotalPoints()
|
||||||
$el.find(".pop-points-open").remove()
|
if not selectedRoleId? or roles.length == 1
|
||||||
|
text = totalPoints
|
||||||
|
title = totalPoints
|
||||||
|
else
|
||||||
|
pointId = @us.points[selectedRoleId]
|
||||||
|
pointObj = @pointsById[pointId]
|
||||||
|
text = "#{pointObj.name} / <span>#{totalPoints}</span>"
|
||||||
|
title = "#{pointObj.name} / #{totalPoints}"
|
||||||
|
|
||||||
# Render into DOM and show the new created element
|
ctx = {
|
||||||
$el.append(html)
|
totalPoints: totalPoints
|
||||||
|
roles: @calculateRoles()
|
||||||
|
editable: @isEditable
|
||||||
|
text: text
|
||||||
|
title: title
|
||||||
|
}
|
||||||
|
mainTemplate = "common/estimation/us-estimation-total.html"
|
||||||
|
template = $tgTemplate.get(mainTemplate, true)
|
||||||
|
html = template(ctx)
|
||||||
|
@$el.html(html)
|
||||||
|
|
||||||
# If not showing role selection let's move to the left
|
estimationProcess.render()
|
||||||
if not $el.find(".pop-role:visible").css("left")?
|
|
||||||
$el.find(".pop-points-open").css("left", "110px")
|
|
||||||
|
|
||||||
$el.find(".pop-points-open").popover().open()
|
|
||||||
|
|
||||||
renderRolesSelector = (us) ->
|
|
||||||
updatePointsRoles()
|
|
||||||
|
|
||||||
|
renderRolesSelector = () ->
|
||||||
|
roles = estimationProcess.calculateRoles()
|
||||||
html = rolesTemplate({"roles": roles})
|
html = rolesTemplate({"roles": roles})
|
||||||
|
|
||||||
# Render into DOM and show the new created element
|
# Render into DOM and show the new created element
|
||||||
$el.append(html)
|
$el.append(html)
|
||||||
$el.find(".pop-role").popover().open(() -> $(this).remove())
|
$el.find(".pop-role").popover().open(() -> $(this).remove())
|
||||||
|
|
||||||
renderPoints = (us, roleId) ->
|
bindClickElements = () ->
|
||||||
dom = $el.find("a > span.points-value")
|
|
||||||
|
|
||||||
if roleId == null or numberOfRoles == 1
|
|
||||||
totalPoints = if us.total_points? then us.total_points else "?"
|
|
||||||
dom.text(totalPoints)
|
|
||||||
dom.parent().prop("title", totalPoints)
|
|
||||||
else
|
|
||||||
pointId = us.points[roleId]
|
|
||||||
pointObj = $scope.pointsById[pointId]
|
|
||||||
dom.html("#{pointObj.name} / <span>#{us.total_points}</span>")
|
|
||||||
dom.parent().prop("title", "#{pointObj.name} / #{us.total_points}")
|
|
||||||
|
|
||||||
calculateTotalPoints = ->
|
|
||||||
values = _.map(us.points, (v, k) -> $scope.pointsById[v].value)
|
|
||||||
values = _.filter(values, (num) -> num?)
|
|
||||||
|
|
||||||
if values.length == 0
|
|
||||||
return "?"
|
|
||||||
|
|
||||||
return _.reduce(values, (acc, num) -> acc + num)
|
|
||||||
|
|
||||||
$scope.$watch $attrs.tgBacklogUsPoints, (us) ->
|
|
||||||
renderPoints(us, selectedRoleId) if us
|
|
||||||
|
|
||||||
$scope.$on "uspoints:select", (ctx, roleId, roleName) ->
|
|
||||||
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
|
||||||
renderPoints(us, roleId)
|
|
||||||
selectedRoleId = roleId
|
|
||||||
|
|
||||||
$scope.$on "uspoints:clear-selection", (ctx) ->
|
|
||||||
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
|
||||||
renderPoints(us, null)
|
|
||||||
selectedRoleId = null
|
|
||||||
|
|
||||||
if roles.length > 0
|
|
||||||
$el.on "click", "a.us-points span", (event) ->
|
$el.on "click", "a.us-points span", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
||||||
updatingSelectedRoleId = selectedRoleId
|
updatingSelectedRoleId = selectedRoleId
|
||||||
|
|
||||||
if selectedRoleId?
|
if selectedRoleId?
|
||||||
renderPointsSelector(us, selectedRoleId)
|
estimationProcess.renderPointsSelector(selectedRoleId)
|
||||||
else
|
else
|
||||||
renderRolesSelector(us)
|
renderRolesSelector()
|
||||||
|
|
||||||
$el.on "click", ".role", (event) ->
|
$el.on "click", ".role", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
|
|
||||||
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
||||||
|
|
||||||
updatingSelectedRoleId = target.data("role-id")
|
updatingSelectedRoleId = target.data("role-id")
|
||||||
|
|
||||||
popRolesDom = $el.find(".pop-role")
|
popRolesDom = $el.find(".pop-role")
|
||||||
popRolesDom.find("a").removeClass("active")
|
popRolesDom.find("a").removeClass("active")
|
||||||
popRolesDom.find("a[data-role-id='#{updatingSelectedRoleId}']").addClass("active")
|
popRolesDom.find("a[data-role-id='#{updatingSelectedRoleId}']").addClass("active")
|
||||||
|
estimationProcess.renderPointsSelector(updatingSelectedRoleId)
|
||||||
renderPointsSelector(us, updatingSelectedRoleId)
|
|
||||||
|
|
||||||
$el.on "click", ".point", (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
|
||||||
$el.find(".pop-points-open").hide()
|
|
||||||
$el.find(".pop-role").hide()
|
|
||||||
|
|
||||||
us = $scope.$eval($attrs.tgBacklogUsPoints)
|
|
||||||
|
|
||||||
points = _.clone(us.points, true)
|
|
||||||
points[updatingSelectedRoleId] = target.data("point-id")
|
|
||||||
|
|
||||||
$scope.$apply ->
|
|
||||||
us.points = points
|
|
||||||
us.total_points = calculateTotalPoints(us)
|
|
||||||
|
|
||||||
renderPoints(us, selectedRoleId)
|
|
||||||
|
|
||||||
$repo.save(us).then ->
|
|
||||||
# Little Hack for refresh.
|
|
||||||
$repo.refresh(us).then ->
|
|
||||||
$ctrl.loadProjectStats()
|
|
||||||
|
|
||||||
bindOnce $scope, "project", (project) ->
|
|
||||||
# If the user has not enough permissions the click events are unbinded
|
|
||||||
if project.my_permissions.indexOf("modify_us") == -1
|
|
||||||
$el.unbind("click")
|
|
||||||
$el.find("a").addClass("not-clickable")
|
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
|
||||||
return {link: link}
|
return {link: link}
|
||||||
|
|
||||||
module.directive("tgBacklogUsPoints", ["$tgRepo", "$tgTemplate", UsPointsDirective])
|
module.directive("tgBacklogUsPoints", ["$tgEstimationsService", "$tgRepo", "$tgTemplate", UsPointsDirective])
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## Burndown graph directive
|
## Burndown graph directive
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
###
|
###
|
||||||
|
|
||||||
taiga = @.taiga
|
taiga = @.taiga
|
||||||
|
groupBy = @.taiga.groupBy
|
||||||
|
|
||||||
module = angular.module("taigaCommon")
|
module = angular.module("taigaCommon")
|
||||||
|
|
||||||
|
@ -27,7 +28,53 @@ module = angular.module("taigaCommon")
|
||||||
## User story estimation directive (for Lightboxes)
|
## User story estimation directive (for Lightboxes)
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
LbUsEstimationDirective = ($rootScope, $repo, $confirm, $template) ->
|
LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $template) ->
|
||||||
|
# Display the points of a US and you can edit it.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# tg-lb-us-estimation-progress-bar(ng-model="us")
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# - Us object (ng-model)
|
||||||
|
# - scope.project object
|
||||||
|
|
||||||
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
|
$scope.$watch $attrs.ngModel, (us) ->
|
||||||
|
if us
|
||||||
|
estimationProcess = $tgEstimationsService.create($el, us, $scope.project)
|
||||||
|
estimationProcess.onSelectedPointForRole = (roleId, pointId) ->
|
||||||
|
$scope.$apply ->
|
||||||
|
$model.$setViewValue(us)
|
||||||
|
|
||||||
|
estimationProcess.render = () ->
|
||||||
|
ctx = {
|
||||||
|
totalPoints: @calculateTotalPoints()
|
||||||
|
roles: @calculateRoles()
|
||||||
|
editable: @isEditable
|
||||||
|
}
|
||||||
|
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
|
||||||
|
template = $template.get(mainTemplate, true)
|
||||||
|
html = template(ctx)
|
||||||
|
@$el.html(html)
|
||||||
|
|
||||||
|
estimationProcess.render()
|
||||||
|
$scope.$on "$destroy", ->
|
||||||
|
$el.off()
|
||||||
|
|
||||||
|
return {
|
||||||
|
link: link
|
||||||
|
restrict: "EA"
|
||||||
|
require: "ngModel"
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgLbUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgTemplate", LbUsEstimationDirective])
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
## User story estimation directive
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qqueue, $template) ->
|
||||||
# Display the points of a US and you can edit it.
|
# Display the points of a US and you can edit it.
|
||||||
#
|
#
|
||||||
# Example:
|
# Example:
|
||||||
|
@ -37,91 +84,26 @@ LbUsEstimationDirective = ($rootScope, $repo, $confirm, $template) ->
|
||||||
# - Us object (ng-model)
|
# - Us object (ng-model)
|
||||||
# - scope.project object
|
# - scope.project object
|
||||||
|
|
||||||
mainTemplate = $template.get("common/estimation/us-estimation-points-per-role.html", true)
|
|
||||||
pointsTemplate = $template.get("common/estimation/us-estimation-points.html", true)
|
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
render = (points) ->
|
$scope.$watch $attrs.ngModel, (us) ->
|
||||||
totalPoints = calculateTotalPoints(points) or 0
|
if us
|
||||||
computableRoles = _.filter($scope.project.roles, "computable")
|
estimationProcess = $tgEstimationsService.create($el, us, $scope.project)
|
||||||
|
estimationProcess.onSelectedPointForRole = (roleId, pointId) ->
|
||||||
|
@save(roleId, pointId).then ->
|
||||||
|
$rootScope.$broadcast("history:reload")
|
||||||
|
|
||||||
roles = _.map computableRoles, (role) ->
|
estimationProcess.render = () ->
|
||||||
pointId = points[role.id]
|
ctx = {
|
||||||
pointObj = $scope.pointsById[pointId]
|
totalPoints: @calculateTotalPoints()
|
||||||
|
roles: @calculateRoles()
|
||||||
|
editable: @isEditable
|
||||||
|
}
|
||||||
|
mainTemplate = "common/estimation/us-estimation-points-per-role.html"
|
||||||
|
template = $template.get(mainTemplate, true)
|
||||||
|
html = template(ctx)
|
||||||
|
@$el.html(html)
|
||||||
|
|
||||||
role = _.clone(role, true)
|
estimationProcess.render()
|
||||||
role.points = if pointObj? and pointObj.name? then pointObj.name else "?"
|
|
||||||
return role
|
|
||||||
|
|
||||||
ctx = {
|
|
||||||
totalPoints: totalPoints
|
|
||||||
roles: roles
|
|
||||||
editable: true
|
|
||||||
}
|
|
||||||
html = mainTemplate(ctx)
|
|
||||||
$el.html(html)
|
|
||||||
|
|
||||||
renderPoints = (target, usPoints, roleId) ->
|
|
||||||
points = _.map $scope.project.points, (point) ->
|
|
||||||
point = _.clone(point, true)
|
|
||||||
point.selected = if usPoints[roleId] == point.id then false else true
|
|
||||||
return point
|
|
||||||
|
|
||||||
html = pointsTemplate({"points": points, roleId: roleId})
|
|
||||||
|
|
||||||
# Remove any prevous state
|
|
||||||
$el.find(".popover").popover().close()
|
|
||||||
$el.find(".pop-points-open").remove()
|
|
||||||
|
|
||||||
# If not showing role selection let's move to the left
|
|
||||||
if not $el.find(".pop-role:visible").css("left")?
|
|
||||||
$el.find(".pop-points-open").css("left", "110px")
|
|
||||||
|
|
||||||
$el.find(".pop-points-open").remove()
|
|
||||||
|
|
||||||
# Render into DOM and show the new created element
|
|
||||||
$el.find(target).append(html)
|
|
||||||
|
|
||||||
$el.find(".pop-points-open").popover().open(-> $(this).removeClass("active"))
|
|
||||||
$el.find(".pop-points-open").show()
|
|
||||||
|
|
||||||
calculateTotalPoints = (points) ->
|
|
||||||
values = _.map(points, (v, k) -> $scope.pointsById[v]?.value or 0)
|
|
||||||
if values.length == 0
|
|
||||||
return "0"
|
|
||||||
return _.reduce(values, (acc, num) -> acc + num)
|
|
||||||
|
|
||||||
$el.on "click", ".total.clickable", (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
|
||||||
roleId = target.data("role-id")
|
|
||||||
|
|
||||||
points = $model.$modelValue
|
|
||||||
renderPoints(target, points, roleId)
|
|
||||||
|
|
||||||
target.siblings().removeClass('active')
|
|
||||||
target.addClass('active')
|
|
||||||
|
|
||||||
$el.on "click", ".point", (event) ->
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
|
||||||
roleId = target.data("role-id")
|
|
||||||
pointId = target.data("point-id")
|
|
||||||
|
|
||||||
$el.find(".popover").popover().close()
|
|
||||||
|
|
||||||
points = _.clone($model.$modelValue, true)
|
|
||||||
points[roleId] = pointId
|
|
||||||
|
|
||||||
$scope.$apply ->
|
|
||||||
$model.$setViewValue(points)
|
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (points) ->
|
|
||||||
render(points) if points
|
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
$scope.$on "$destroy", ->
|
||||||
$el.off()
|
$el.off()
|
||||||
|
@ -132,81 +114,46 @@ LbUsEstimationDirective = ($rootScope, $repo, $confirm, $template) ->
|
||||||
require: "ngModel"
|
require: "ngModel"
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgLbUsEstimation", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgTemplate", LbUsEstimationDirective])
|
module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate",
|
||||||
|
UsEstimationDirective])
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
## User story estimation directive
|
## Estimations service
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
UsEstimationDirective = ($rootScope, $repo, $confirm, $qqueue, $template) ->
|
EstimationsService = ($template, $qqueue, $repo, $confirm, $q) ->
|
||||||
# Display the points of a US and you can edit it.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# tg-us-estimation-progress-bar(ng-model="us")
|
|
||||||
#
|
|
||||||
# Requirements:
|
|
||||||
# - Us object (ng-model)
|
|
||||||
# - scope.project object
|
|
||||||
|
|
||||||
mainTemplate = $template.get("common/estimation/us-estimation-points-per-role.html", true)
|
|
||||||
pointsTemplate = $template.get("common/estimation/us-estimation-points.html", true)
|
pointsTemplate = $template.get("common/estimation/us-estimation-points.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
class EstimationProcess
|
||||||
isEditable = ->
|
constructor: (@$el, @us, @project) ->
|
||||||
return $scope.project.my_permissions.indexOf("modify_us") != -1
|
@isEditable = @project.my_permissions.indexOf("modify_us") != -1
|
||||||
|
@roles = @project.roles
|
||||||
|
@points = @project.points
|
||||||
|
@pointsById = groupBy(@points, (x) -> x.id)
|
||||||
|
@onSelectedPointForRole = (roleId, pointId) ->
|
||||||
|
@render = () ->
|
||||||
|
|
||||||
render = (us) ->
|
save: (roleId, pointId) ->
|
||||||
totalPoints = calculateTotalPoints(us.points) or "?"
|
deferred = $q.defer()
|
||||||
computableRoles = _.filter($scope.project.roles, "computable")
|
$qqueue.add () =>
|
||||||
|
onSuccess = =>
|
||||||
|
deferred.resolve()
|
||||||
|
$confirm.notify("success")
|
||||||
|
|
||||||
roles = _.map computableRoles, (role) ->
|
onError = =>
|
||||||
pointId = us.points[role.id]
|
$confirm.notify("error")
|
||||||
pointObj = $scope.pointsById[pointId]
|
@us.revert()
|
||||||
|
@render()
|
||||||
|
deferred.reject()
|
||||||
|
|
||||||
role = _.clone(role, true)
|
$repo.save(@us).then(onSuccess, onError)
|
||||||
role.points = if pointObj? and pointObj.name? then pointObj.name else "?"
|
|
||||||
return role
|
|
||||||
|
|
||||||
ctx = {
|
return deferred.promise
|
||||||
totalPoints: totalPoints
|
|
||||||
roles: roles
|
|
||||||
editable: isEditable()
|
|
||||||
}
|
|
||||||
html = mainTemplate(ctx)
|
|
||||||
$el.html(html)
|
|
||||||
|
|
||||||
renderPoints = (target, us, roleId) ->
|
calculateTotalPoints: () ->
|
||||||
points = _.map $scope.project.points, (point) ->
|
values = _.map(@us.points, (v, k) => @pointsById[v]?.value)
|
||||||
point = _.clone(point, true)
|
|
||||||
point.selected = if us.points[roleId] == point.id then false else true
|
|
||||||
return point
|
|
||||||
|
|
||||||
html = pointsTemplate({"points": points, roleId: roleId})
|
|
||||||
|
|
||||||
# Remove any prevous state
|
|
||||||
$el.find(".popover").popover().close()
|
|
||||||
$el.find(".pop-points-open").remove()
|
|
||||||
|
|
||||||
# If not showing role selection let's move to the left
|
|
||||||
if not $el.find(".pop-role:visible").css("left")?
|
|
||||||
$el.find(".pop-points-open").css("left", "110px")
|
|
||||||
|
|
||||||
$el.find(".pop-points-open").remove()
|
|
||||||
|
|
||||||
# Render into DOM and show the new created element
|
|
||||||
$el.find(target).append(html)
|
|
||||||
|
|
||||||
$el.find(".pop-points-open").popover().open ->
|
|
||||||
$(this)
|
|
||||||
.removeClass("active")
|
|
||||||
.closest("li").removeClass("active")
|
|
||||||
|
|
||||||
|
|
||||||
$el.find(".pop-points-open").show()
|
|
||||||
|
|
||||||
calculateTotalPoints = (points) ->
|
|
||||||
values = _.map(points, (v, k) -> $scope.pointsById[v]?.value)
|
|
||||||
if values.length == 0
|
if values.length == 0
|
||||||
return "0"
|
return "0"
|
||||||
|
|
||||||
|
@ -216,62 +163,74 @@ UsEstimationDirective = ($rootScope, $repo, $confirm, $qqueue, $template) ->
|
||||||
|
|
||||||
return _.reduce(notNullValues, (acc, num) -> acc + num)
|
return _.reduce(notNullValues, (acc, num) -> acc + num)
|
||||||
|
|
||||||
save = $qqueue.bindAdd (roleId, pointId) =>
|
calculateRoles: () ->
|
||||||
$el.find(".popover").popover().close()
|
computableRoles = _.filter(@project.roles, "computable")
|
||||||
|
roles = _.map computableRoles, (role) =>
|
||||||
|
pointId = @us.points[role.id]
|
||||||
|
pointObj = @pointsById[pointId]
|
||||||
|
role = _.clone(role, true)
|
||||||
|
role.points = if pointObj? and pointObj.name? then pointObj.name else "?"
|
||||||
|
return role
|
||||||
|
|
||||||
points = _.clone($model.$modelValue.points, true)
|
return roles
|
||||||
points[roleId] = pointId
|
|
||||||
|
|
||||||
us = $model.$modelValue.clone()
|
bindClickEvents: =>
|
||||||
us.points = points
|
@$el.on "click", ".total.clickable", (event) =>
|
||||||
$model.$setViewValue(us)
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
target = angular.element(event.currentTarget)
|
||||||
|
roleId = target.data("role-id")
|
||||||
|
@renderPointsSelector(roleId, target)
|
||||||
|
target.siblings().removeClass('active')
|
||||||
|
target.addClass('active')
|
||||||
|
|
||||||
onSuccess = ->
|
@$el.on "click", ".point", (event) =>
|
||||||
$confirm.notify("success")
|
event.preventDefault()
|
||||||
$rootScope.$broadcast("history:reload")
|
event.stopPropagation()
|
||||||
onError = ->
|
target = angular.element(event.currentTarget)
|
||||||
$confirm.notify("error")
|
roleId = target.data("role-id")
|
||||||
us.revert()
|
pointId = target.data("point-id")
|
||||||
$model.$setViewValue(us)
|
@$el.find(".popover").popover().close()
|
||||||
|
points = _.clone(@us.points, true)
|
||||||
|
points[roleId] = pointId
|
||||||
|
@us.points = points
|
||||||
|
@render()
|
||||||
|
@onSelectedPointForRole(roleId, pointId)
|
||||||
|
|
||||||
$repo.save(us).then(onSuccess, onError)
|
renderPointsSelector: (roleId, target) ->
|
||||||
|
points = _.map @points, (point) =>
|
||||||
|
point = _.clone(point, true)
|
||||||
|
point.selected = if @us.points[roleId] == point.id then false else true
|
||||||
|
return point
|
||||||
|
|
||||||
$el.on "click", ".total.clickable", (event) ->
|
html = pointsTemplate({"points": points, roleId: roleId})
|
||||||
event.preventDefault()
|
# Remove any previous state
|
||||||
event.stopPropagation()
|
@$el.find(".popover").popover().close()
|
||||||
return if not isEditable()
|
@$el.find(".pop-points-open").remove()
|
||||||
|
# Render into DOM and show the new created element
|
||||||
|
if target?
|
||||||
|
@$el.find(target).append(html)
|
||||||
|
else
|
||||||
|
@$el.append(html)
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
@$el.find(".pop-points-open").popover().open ->
|
||||||
roleId = target.data("role-id")
|
$(this)
|
||||||
|
.removeClass("active")
|
||||||
|
.closest("li").removeClass("active")
|
||||||
|
|
||||||
us = $model.$modelValue
|
@$el.find(".pop-points-open").show()
|
||||||
renderPoints(target, us, roleId)
|
|
||||||
|
|
||||||
target.siblings().removeClass('active')
|
create = ($el, us, project) ->
|
||||||
target.addClass('active')
|
estimationProcess = new EstimationProcess($el, us, project)
|
||||||
|
if estimationProcess.isEditable
|
||||||
|
estimationProcess.bindClickEvents()
|
||||||
|
else
|
||||||
|
$el.unbind("click")
|
||||||
|
|
||||||
$el.on "click", ".point", (event) ->
|
return estimationProcess
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
return if not isEditable()
|
|
||||||
|
|
||||||
target = angular.element(event.currentTarget)
|
|
||||||
roleId = target.data("role-id")
|
|
||||||
pointId = target.data("point-id")
|
|
||||||
|
|
||||||
save(roleId, pointId)
|
|
||||||
|
|
||||||
$scope.$watch $attrs.ngModel, (us) ->
|
|
||||||
render(us) if us
|
|
||||||
|
|
||||||
$scope.$on "$destroy", ->
|
|
||||||
$el.off()
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
link: link
|
create: create
|
||||||
restrict: "EA"
|
|
||||||
require: "ngModel"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgUsEstimation", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate",
|
module.factory("$tgEstimationsService", ["$tgTemplate", "$tgQqueue", "$tgRepo", "$tgConfirm", "$q", EstimationsService])
|
||||||
UsEstimationDirective])
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
a.us-points(href="", title!="<%= title %>", class!="<% if (!editable) { %>not-clickable<% } %>")
|
||||||
|
span.points-value <%= text %>
|
||||||
|
<% if (editable) { %>
|
||||||
|
span.icon.icon-arrow-bottom(tg-check-permission="modify_us")
|
||||||
|
<% } %>
|
|
@ -20,7 +20,5 @@ div.row.us-item-row(ng-repeat="us in visibleUserstories track by us.id", tg-drag
|
||||||
|
|
||||||
div.points(tg-backlog-us-points="us")
|
div.points(tg-backlog-us-points="us")
|
||||||
a.us-points(href="", title="Points")
|
a.us-points(href="", title="Points")
|
||||||
span.points-value 0
|
|
||||||
span.icon.icon-arrow-bottom(tg-check-permission="modify_us")
|
|
||||||
|
|
||||||
a.icon.icon-drag-v(tg-check-permission="modify_us", href="", title="Drag")
|
a.icon.icon-drag-v(tg-check-permission="modify_us", href="", title="Drag")
|
||||||
|
|
|
@ -7,7 +7,7 @@ form
|
||||||
data-required="true", data-maxlength="500")
|
data-required="true", data-maxlength="500")
|
||||||
|
|
||||||
fieldset.estimation
|
fieldset.estimation
|
||||||
tg-lb-us-estimation(ng-model="us.points")
|
tg-lb-us-estimation(ng-model="us")
|
||||||
|
|
||||||
fieldset
|
fieldset
|
||||||
select(name="status", ng-model="us.status", ng-options="s.id as s.name for s in usStatusList",
|
select(name="status", ng-model="us.status", ng-options="s.id as s.name for s in usStatusList",
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
padding-right: 3rem;
|
padding-right: 3rem;
|
||||||
}
|
}
|
||||||
.pop-points-open {
|
.pop-points-open {
|
||||||
@include popover(200px, 0, 260px, '', '');
|
@include popover(200px, 0, 30px, '', '');
|
||||||
li {
|
li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 23%;
|
width: 23%;
|
||||||
|
|
Loading…
Reference in New Issue