From 7248d7e02feb6fc273db46bb5ee0dcae8cf631a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Fri, 14 Nov 2014 01:10:31 +0100 Subject: [PATCH 1/2] Fix error: undefined is not a function (evaluating \'$scope.us.revert()\') --- app/coffee/modules/common/lightboxes.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/coffee/modules/common/lightboxes.coffee b/app/coffee/modules/common/lightboxes.coffee index 7ca4d0d8..a8c33c7b 100644 --- a/app/coffee/modules/common/lightboxes.coffee +++ b/app/coffee/modules/common/lightboxes.coffee @@ -240,13 +240,13 @@ CreateEditUserstoryDirective = ($repo, $model, $rs, $rootScope, lightboxService, $scope.isNew = true $scope.usStatusList = statusList - $scope.us = { + $scope.us = $model.make_model("userstories", { project: projectId points : {} status: status is_archived: false tags: [] - } + }) # Update texts for creation $el.find(".button-green span").html("Create") #TODO: i18n From 7167769a868d4f53cdb5af838ce5b6171433c291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Fri, 14 Nov 2014 01:12:33 +0100 Subject: [PATCH 2/2] Fix error: Extrange behavior of tg-us-estimation in lightboxes --- app/coffee/modules/common/estimation.coffee | 318 ++++++++++++++++++ app/coffee/modules/userstories/detail.coffee | 169 ---------- app/partials/us-detail.jade | 2 +- .../modules/lightbox-us-create-edit.jade | 2 +- 4 files changed, 320 insertions(+), 171 deletions(-) create mode 100644 app/coffee/modules/common/estimation.coffee diff --git a/app/coffee/modules/common/estimation.coffee b/app/coffee/modules/common/estimation.coffee new file mode 100644 index 00000000..48474107 --- /dev/null +++ b/app/coffee/modules/common/estimation.coffee @@ -0,0 +1,318 @@ +### +# Copyright (C) 2014 Andrey Antukh +# Copyright (C) 2014 Jesús Espino Garcia +# Copyright (C) 2014 David Barragán Merino +# +# 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 . +# +# File: modules/common/estimation.coffee +### + +taiga = @.taiga + +module = angular.module("taigaCommon") + +############################################################################# +## User story estimation directive (for Lightboxes) +############################################################################# + +LbUsEstimationDirective = ($rootScope, $repo, $confirm) -> + # 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(""" +
    +
  • + <%- totalPoints %> + total +
  • + <% _.each(roles, function(role) { %> +
  • + <%- role.points %> + <%- role.name %>
  • + <% }); %> +
+ """) + + pointsTemplate = _.template(""" + + """) + + link = ($scope, $el, $attrs, $model) -> + render = (points) -> + totalPoints = calculateTotalPoints(points) or 0 + computableRoles = _.filter($scope.project.roles, "computable") + + roles = _.map computableRoles, (role) -> + pointId = points[role.id] + pointObj = $scope.pointsById[pointId] + + role = _.clone(role, true) + role.points = if pointObj? and pointObj.name? then pointObj.name else "?" + return role + + ctx = { + totalPoints: totalPoints + roles: roles + } + 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", -> + $el.off() + + return { + link: link + restrict: "EA" + require: "ngModel" + } + +module.directive("tgLbUsEstimation", ["$rootScope", "$tgRepo", "$tgConfirm", LbUsEstimationDirective]) + + +############################################################################# +## User story estimation directive +############################################################################# + +UsEstimationDirective = ($rootScope, $repo, $confirm) -> + # 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(""" +
    +
  • + <%- totalPoints %> + total +
  • + <% _.each(roles, function(role) { %> +
  • + <%- role.points %> + <%- role.name %>
  • + <% }); %> +
+ """) + + pointsTemplate = _.template(""" + + """) + + link = ($scope, $el, $attrs, $model) -> + isEditable = -> + return $scope.project.my_permissions.indexOf("modify_us") != -1 + + render = (us) -> + totalPoints = us.total_points or 0 + computableRoles = _.filter($scope.project.roles, "computable") + + roles = _.map computableRoles, (role) -> + pointId = us.points[role.id] + pointObj = $scope.pointsById[pointId] + + role = _.clone(role, true) + role.points = if pointObj? and pointObj.name? then pointObj.name else "?" + return role + + ctx = { + totalPoints: totalPoints + roles: roles + editable: isEditable() + } + html = mainTemplate(ctx) + $el.html(html) + + renderPoints = (target, us, roleId) -> + 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}) + + # 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 = (us) -> + values = _.map(us.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() + return if not isEditable() + + target = angular.element(event.currentTarget) + roleId = target.data("role-id") + + us = $model.$modelValue + renderPoints(target, us, roleId) + + target.siblings().removeClass('active') + target.addClass('active') + + $el.on "click", ".point", (event) -> + event.preventDefault() + event.stopPropagation() + return if not isEditable() + + target = angular.element(event.currentTarget) + roleId = target.data("role-id") + pointId = target.data("point-id") + + $el.find(".popover").popover().close() + + # Hell starts here + us = angular.copy($model.$modelValue) + points = _.clone($model.$modelValue.points, true) + points[roleId] = pointId + us.setAttr('points', points) + us.points = points + us.total_points = calculateTotalPoints(us) + $model.$setViewValue(us) + # Hell ends here + + onSuccess = -> + $confirm.notify("success") + $rootScope.$broadcast("history:reload") + onError = -> + $confirm.notify("error") + us.revert() + $model.$setViewValue(us) + $repo.save($model.$modelValue).then(onSuccess, onError) + + $scope.$watch $attrs.ngModel, (us) -> + render(us) if us + + $scope.$on "$destroy", -> + $el.off() + + return { + link: link + restrict: "EA" + require: "ngModel" + } + +module.directive("tgUsEstimation", ["$rootScope", "$tgRepo", "$tgConfirm", UsEstimationDirective]) diff --git a/app/coffee/modules/userstories/detail.coffee b/app/coffee/modules/userstories/detail.coffee index 71e7a8a7..60a8343f 100644 --- a/app/coffee/modules/userstories/detail.coffee +++ b/app/coffee/modules/userstories/detail.coffee @@ -255,175 +255,6 @@ UsTasksProgressDisplayDirective = -> module.directive("tgUsTasksProgressDisplay", UsTasksProgressDisplayDirective) -############################################################################# -## User story estimation directive -############################################################################# - -UsEstimationDirective = ($rootScope, $repo, $confirm) -> - # 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 - # Optionals: - # - save-after-modify (boolean): save object after modify - - mainTemplate = _.template(""" -
    -
  • - <%- totalPoints %> - total -
  • - <% _.each(roles, function(role) { %> -
  • - <%- role.points %> - <%- role.name %>
  • - <% }); %> -
- """) - - pointsTemplate = _.template(""" - - """) - - link = ($scope, $el, $attrs, $model) -> - saveAfterModify = $attrs.saveAfterModify or false - - isEditable = -> - if $model.$modelValue.id - return $scope.project.my_permissions.indexOf("modify_us") != -1 - return $scope.project.my_permissions.indexOf("add_us") != -1 - - render = (us) -> - totalPoints = us.total_points or 0 - computableRoles = _.filter($scope.project.roles, "computable") - - roles = _.map computableRoles, (role) -> - pointId = us.points[role.id] - pointObj = $scope.pointsById[pointId] - - role = _.clone(role, true) - role.points = if pointObj? and pointObj.name? then pointObj.name else "?" - return role - - ctx = { - totalPoints: totalPoints - roles: roles - editable: isEditable() - } - html = mainTemplate(ctx) - $el.html(html) - - renderPoints = (target, us, roleId) -> - 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}) - - # 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 = (us) -> - values = _.map(us.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() - return if not isEditable() - - target = angular.element(event.currentTarget) - roleId = target.data("role-id") - - us = $model.$modelValue - renderPoints(target, us, roleId) - - target.siblings().removeClass('active') - target.addClass('active') - - $el.on "click", ".point", (event) -> - event.preventDefault() - event.stopPropagation() - return if not isEditable() - - target = angular.element(event.currentTarget) - roleId = target.data("role-id") - pointId = target.data("point-id") - - $el.find(".popover").popover().close() - - # NOTE: This block of code is strange and, sometimes, repetitive - # but is the only solution I find to update the object - # corectly - us = angular.copy($model.$modelValue) - points = _.clone($model.$modelValue.points, true) - points[roleId] = pointId - us.setAttr('points', points) if us.setAttr? - us.points = points - us.total_points = calculateTotalPoints(us) - $model.$setViewValue(us) - - if saveAfterModify - # Edit in the detail page - onSuccess = -> - $confirm.notify("success") - $rootScope.$broadcast("history:reload") - onError = -> - us.revert() - $model.$setViewValue(us) - $confirm.notify("error") - $repo.save($model.$modelValue).then(onSuccess, onError) - else - # Create or eedit in the lightbox - render($model.$modelValue) - - $scope.$watch $attrs.ngModel, (us) -> - render(us) if us - - $scope.$on "$destroy", -> - $el.off() - - return { - link: link - restrict: "EA" - require: "ngModel" - } - -module.directive("tgUsEstimation", ["$rootScope", "$tgRepo", "$tgConfirm", UsEstimationDirective]) - - ############################################################################# ## User story status button directive ############################################################################# diff --git a/app/partials/us-detail.jade b/app/partials/us-detail.jade index 14f05a05..eb66d449 100644 --- a/app/partials/us-detail.jade +++ b/app/partials/us-detail.jade @@ -51,7 +51,7 @@ block content h1(tg-us-status-display, ng-model="us") div.us-detail-progress-bar(tg-us-tasks-progress-display, ng-model="tasks") tg-created-by-display.us-created-by(ng-model="us") - tg-us-estimation(ng-model="us", save-after-modify="true") + tg-us-estimation(ng-model="us") div.duty-data-container div.duty-data(tg-us-status-button, ng-model="us") diff --git a/app/partials/views/modules/lightbox-us-create-edit.jade b/app/partials/views/modules/lightbox-us-create-edit.jade index 15808251..73d379c2 100644 --- a/app/partials/views/modules/lightbox-us-create-edit.jade +++ b/app/partials/views/modules/lightbox-us-create-edit.jade @@ -7,7 +7,7 @@ form data-required="true", data-maxlength="500") fieldset.estimation - tg-us-estimation(ng-model="us") + tg-lb-us-estimation(ng-model="us.points") fieldset select(name="status", ng-model="us.status", ng-options="s.id as s.name for s in usStatusList",