From 982be3316f354b384865ed7c58701e5831864c03 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 25 Jun 2014 17:48:19 +0200 Subject: [PATCH] Implementing points behaviour in backlog --- app/coffee/modules/backlog/main.coffee | 156 +++++++++++++++++- .../views/components/backlog-row.jade | 17 +- app/partials/views/components/summary.jade | 2 +- app/partials/views/modules/backlog-table.jade | 9 +- app/styles/modules/backlog-table.scss | 3 + 5 files changed, 173 insertions(+), 14 deletions(-) diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index c5cb1eec..e5c580c9 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -63,6 +63,10 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin) return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project @scope.points = _.sortBy(project.points, "order") + @scope.pointsById = {} + for p in @scope.points + @scope.pointsById[p.id] = p + @scope.statusList = _.sortBy(project.us_statuses, "id") return project @@ -192,6 +196,7 @@ BacklogDirective = ($repo) -> ############################## ## Move to current sprint link ############################## + linkMoveToCurrentSprint = ($scope, $el, $attrs, $ctrl) -> moveToCurrentSprint = (selectedUss) -> @@ -367,14 +372,159 @@ BacklogSprintDirective = ($repo) -> return {link: link} -BacklogSummaryDirective = -> +############################################################################# +## User story points directive +############################################################################# + +UsRolePointsSelectorDirective = ($rootscope) -> + #TODO: i18n + selectionTemplate = _.template(""" + + """) link = ($scope, $el, $attrs) -> - return {link:link} + taiga.bindOnce $scope, "project", (project) -> + roles = _.filter(project.roles, "computable") + $el.append(selectionTemplate({ 'roles': roles })) + + $scope.$on "uspoints:select", (ctx, roleId, roleName) -> + $el.find(".popover").hide() + $el.find("span").text(roleName) + + $scope.$on "uspoints:clear-selection", (ctx, roleId) -> + $el.find(".popover").hide() + $el.find("span").text("Points") #TODO: i18n + + $el.on "click", (event) -> + target = angular.element(event.target) + + if target.is("span") or target.is("div") + event.stopPropagation() + + $el.find(".popover").show() + body = angular.element("body") + body.one "click", (event) -> + $el.find(".popover").hide() + + $el.on "click", ".clear-selection", (event) -> + event.preventDefault() + event.stopPropagation() + $rootscope.$broadcast("uspoints:clear-selection") + + $el.on "click", ".role", (event) -> + event.preventDefault() + event.stopPropagation() + target = angular.element(event.currentTarget) + rolScope = target.scope() + $rootscope.$broadcast("uspoints:select", target.data("role-id"), target.text()) + + $scope.$on "$destroy", -> + $el.off() + + return {link: link} + +UsPointsDirective = ($repo) -> + selectionTemplate = _.template(""" + + """) + pointsTemplate = _.template(""" + + """) + + updatePointsValue = (us, pointsById, pointsDomNode, selectedRoleId) -> + if not selectedRoleId? + pointsDomNode.text(us.total_points) + else + selectedPoints = pointsById[us.points[selectedRoleId]] + selectedPointsValue = selectedPoints.value + selectedPointsValue = '?' if not selectedPointsValue? + pointsDomNode.text("#{selectedPointsValue}/#{us.total_points}") + + link = ($scope, $el, $attrs) -> + $ctrl = $el.controller() + us = $scope.$eval($attrs.tgUsPoints) + usPoints = us.points + pointsDom = $el.find("a") + selectedRoleId = null + updatingSelectedRoleId = null + pointsById = $scope.pointsById + updatePointsValue(us, pointsById, pointsDom, selectedRoleId) + + taiga.bindOnce $scope, "project", (project) -> + roles = _.filter(project.roles, "computable") + $el.append(selectionTemplate({ 'roles': roles })) + $el.append(pointsTemplate({ 'points': project.points })) + + $scope.$on "uspoints:select", (ctx, roleId,roleName) -> + selectedRoleId = roleId + updatePointsValue(us, pointsById, pointsDom, selectedRoleId) + + $scope.$on "uspoints:clear-selection", (ctx) -> + selectedRoleId = null + updatePointsValue(us, pointsById, pointsDom, selectedRoleId) + + $el.on "click", "a.us-points", (event) -> + event.preventDefault() + target = angular.element(event.target) + + if target.is("a") + event.stopPropagation() + + if selectedRoleId? + updatingSelectedRoleId = selectedRoleId + $el.find(".pop-points-open").show() + else + $el.find(".pop-role").show() + + body = angular.element("body") + body.one "click", (event) -> + $el.find(".popover").hide() + + $el.on "click", ".role", (event) -> + event.preventDefault() + event.stopPropagation() + target = angular.element(event.currentTarget) + updatingSelectedRoleId = target.data("role-id") + $el.find(".pop-points-open").show() + $el.find(".pop-role").hide() + + $el.on "click", ".point", (event) -> + event.preventDefault() + event.stopPropagation() + target = angular.element(event.currentTarget) + $el.find(".pop-points-open").hide() + $scope.$apply () -> + usPoints[updatingSelectedRoleId] = target.data("point-id") + us.points = _.clone(usPoints, false) + total = _.reduce(_.map(us.points, (value, key) -> $scope.pointsById[value].value), (memo, num) -> memo + num) + us.total_points = total + updatePointsValue(us, pointsById, pointsDom, selectedRoleId) + $repo.save(us).then -> + $ctrl.loadProjectStats() + + $scope.$on "$destroy", -> + $el.off() + + return {link: link} + module = angular.module("taigaBacklog") module.directive("tgBacklog", ["$tgRepo", BacklogDirective]) module.directive("tgBacklogSprint", ["$tgRepo", BacklogSprintDirective]) -module.directive("tgBacklogSummary", BacklogSummaryDirective) +module.directive("tgUsPoints", ["$tgRepo", UsPointsDirective]) +module.directive("tgUsRolePointsSelector", ["$rootScope", UsRolePointsSelectorDirective]) module.controller("BacklogController", [ "$scope", diff --git a/app/partials/views/components/backlog-row.jade b/app/partials/views/components/backlog-row.jade index be693ba7..50d8e6e2 100644 --- a/app/partials/views/components/backlog-row.jade +++ b/app/partials/views/components/backlog-row.jade @@ -8,7 +8,18 @@ div.row.us-item-row(ng-repeat="us in visibleUserstories track by us.id") a.icon.icon-delete(href="", ng-click="ctrl.deleteUserStory(us)", title="Delete") div.user-story-tags span.tag(ng-repeat="tag in us.tags") {{ tag }} - div.status Status - div.points 12 - div.points 54 + + div.status.width-2 + a(href="", title="Status Name") Status Name + ul.popover.pop-status + li + a(href="", title="Status 1") Status 1 + li + a(href="", title="Status 2") Status 2 + li + a(href="", title="Status 3") Status 3 + + div.points(tg-us-points="us") + a.us-points(href="", title="Points") 0 + a.icon.icon-drag-v(href="", title="Drag") diff --git a/app/partials/views/components/summary.jade b/app/partials/views/components/summary.jade index 178d84f1..7283a2f0 100644 --- a/app/partials/views/components/summary.jade +++ b/app/partials/views/components/summary.jade @@ -1,4 +1,4 @@ -div.summary(tg-backlog-summary) +div.summary div.summary-progress-bar div.current-progress div.data diff --git a/app/partials/views/modules/backlog-table.jade b/app/partials/views/modules/backlog-table.jade index b0dde643..ac290bd8 100644 --- a/app/partials/views/modules/backlog-table.jade +++ b/app/partials/views/modules/backlog-table.jade @@ -2,13 +2,8 @@ section.backlog-table-header div.row.backlog-table-title div.user-stories User Stories div.status Status - div.points Points - div.points - div.row.backlog-table-subtitle - div.user-stories.width-4 - div.status.width-2 - div.points.width-1 Front - div.points.width-1 Total + div.points(tg-us-role-points-selector) + span Points section.backlog-table-body include ../components/backlog-row diff --git a/app/styles/modules/backlog-table.scss b/app/styles/modules/backlog-table.scss index 510b7f6c..ef4597c8 100644 --- a/app/styles/modules/backlog-table.scss +++ b/app/styles/modules/backlog-table.scss @@ -32,6 +32,9 @@ .points { position: relative; } + .pop-role { + @include popover(150px, '', 30px, 10px, ''); + } .pop-status { @include popover(150px, '', 30px, 10px, ''); }