diff --git a/app/coffee/modules/issues/detail.coffee b/app/coffee/modules/issues/detail.coffee index d7fc4c02..2a3c5d2d 100644 --- a/app/coffee/modules/issues/detail.coffee +++ b/app/coffee/modules/issues/detail.coffee @@ -370,8 +370,8 @@ AssignedToDirective = ($rootscope, $confirm) -> html = template({assignedTo: assignedTo, editable:editable}) $el.html(html) - $scope.$watch $attrs.ngModel, (issue) -> - renderAssignedTo(issue) + $scope.$watch $attrs.ngModel, (instance) -> + renderAssignedTo(instance) $el.on "click", ".user-assigned", (event) -> event.preventDefault() @@ -384,7 +384,8 @@ AssignedToDirective = ($rootscope, $confirm) -> title = "Remove assigned to" subtitle = "" $confirm.ask(title, subtitle).then => - $model.$setViewValue(null) + $model.$modelValue.assigned_to = null + renderAssignedTo($model.$modelValue) $scope.$on "assigned-to:added", (ctx, issue) -> renderAssignedTo(issue) @@ -408,7 +409,7 @@ IssueStatusDirective = () -> <% } else { %> Open <% } %> - <%= status.name %> + <%= status.name %>
diff --git a/app/coffee/modules/userstories/detail.coffee b/app/coffee/modules/userstories/detail.coffee index 2629df74..5ead6633 100644 --- a/app/coffee/modules/userstories/detail.coffee +++ b/app/coffee/modules/userstories/detail.coffee @@ -23,6 +23,7 @@ taiga = @.taiga mixOf = @.taiga.mixOf groupBy = @.taiga.groupBy +bindOnce = @.taiga.bindOnce module = angular.module("taigaUserStories") @@ -53,7 +54,7 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin) loadProject: -> return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project - @scope.statusList = project.issue_statuses + @scope.statusList = project.us_statuses @scope.statusById = groupBy(project.us_statuses, (x) -> x.id) @scope.taskStatusById = groupBy(project.task_statuses, (x) -> x.id) @scope.membersById = groupBy(project.memberships, (x) -> x.user) @@ -69,13 +70,8 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin) @scope.nextUrl = "/project/#{@scope.project.slug}/us/#{@scope.us.neighbors.next.ref}" if @scope.us.neighbors.next.id? loadTasks: -> - # http://localhost:8000/api/v1/tasks?user_story=6 return @rs.tasks.list(@scope.projectId, null, @scope.usId).then (tasks) => @scope.tasks = tasks - @scope.totalTasks = tasks.length - closedTasks = _.filter(tasks, (task) => @scope.taskStatusById[task.status].is_closed) - @scope.totalClosedTasks = closedTasks.length - @scope.usProgress = 100 * @scope.totalClosedTasks / @scope.totalTasks loadHistory: -> return @rs.userstories.history(@scope.usId).then (history) => @@ -128,6 +124,22 @@ class UserStoryDetailController extends mixOf(taiga.Controller, taiga.PageMixin) return "Made #{size} changes" + block: -> + @rootscope.$broadcast("block", @scope.us) + + unblock: -> + @rootscope.$broadcast("unblock", @scope.us) + + + delete: -> + #TODO: i18n + title = "Delete User Story" + subtitle = @scope.us.subject + + @confirm.ask(title, subtitle).then => + @.repo.remove(@scope.us).then => + @location.path("/project/#{@scope.project.slug}/backlog") + module.controller("UserStoryDetailController", UserStoryDetailController) @@ -176,8 +188,28 @@ UsStatusDetailDirective = () -> <% } else { %> Open <% } %> - <%= status.name %> + <%= status.name %> + +
+
+ + <%- totalClosedTasks %>/<%- totalTasks %> tasks completed + +
+ +
    +
  • + <%- totalPoints %> + total +
  • + <% _.each(rolePoints, function(rolePoint) { %> +
  • + <%- rolePoint.points %> + <%- rolePoint.name %>
  • + <% }); %> +
+
@@ -187,29 +219,69 @@ UsStatusDetailDirective = () ->
""") selectionStatusTemplate = _.template(""" - + + """) + selectionPointsTemplate = _.template(""" + """) link = ($scope, $el, $attrs, $model) -> editable = $attrs.editable? + updatingSelectedRoleId = null + + showSelectPoints = () -> + us = $model.$modelValue + $el.find(".pop-points-open").remove() + $el.find(".points-per-role").append(selectionPointsTemplate({ "points": $scope.project.points })) + $el.find(".pop-points-open a[data-point-id='#{us.points[updatingSelectedRoleId]}']").addClass("active") + # If not showing role selection let's move to the left + $el.find(".pop-points-open").show() + + calculateTotalPoints = (us)-> + 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) renderUsstatus = (us) -> status = $scope.statusById[us.status] + rolePoints = _.clone(_.filter($scope.project.roles, "computable"), true) + _.map rolePoints, (v, k) -> + val = $scope.pointsById[us.points[v.id]].value + val = "?" if not val? + v.points = val + + totalTasks = $scope.tasks.length + totalClosedTasks = _.filter($scope.tasks, (task) => $scope.taskStatusById[task.status].is_closed).length html = template({ editable: editable status: status + totalPoints: us.total_points + rolePoints: rolePoints + totalTasks: totalTasks + totalClosedTasks: totalClosedTasks + usProgress: 100 * totalClosedTasks / totalTasks }) $el.html(html) $el.find(".status-data").append(selectionStatusTemplate({statuses:$scope.statusList})) - $scope.$watch $attrs.ngModel, (us) -> - if us? - renderUsstatus(us) + bindOnce $scope, "tasks", (tasks) -> + $scope.$watch $attrs.ngModel, (us) -> + if us? + renderUsstatus(us) if editable $el.on "click", ".status-data", (event) -> @@ -228,66 +300,31 @@ UsStatusDetailDirective = () -> renderUsstatus($model.$modelValue) $el.find(".popover").hide() + $el.on "click", ".total.clickable", (event) -> + event.preventDefault() + event.stopPropagation() + target = angular.element(event.currentTarget) + updatingSelectedRoleId = target.data("role-id") + showSelectPoints() + body = angular.element("body") + body.one "click", (event) -> + $el.find(".popover").hide() + + $el.on "click", ".point", (event) -> + event.preventDefault() + event.stopPropagation() + + target = angular.element(event.currentTarget) + $el.find(".popover").hide() + + $scope.$apply () -> + us = $model.$modelValue + usPoints = _.clone(us.points, true) + usPoints[updatingSelectedRoleId] = target.data("point-id") + us.points = usPoints + us.total_points = calculateTotalPoints(us) + renderUsstatus(us) + return {link:link, require:"ngModel"} module.directive("tgUsStatusDetail", UsStatusDetailDirective) - - - - - - - - - - - - -############################################################################# -## User story points detail directive -############################################################################# - -USPointsDetailDirective = () -> - #TODO: i18n - template = _.template(""" -
    -
  • - <%- totalPoints %> - total -
  • - <% _.each(rolePoints, function(rolePoint) { %> -
  • - <%- rolePoint.points %> - <%- rolePoint.name %>
  • - <% }); %> -
- """) - - link = ($scope, $el, $attrs, $model) -> - editable = $attrs.editable? - - renderUsPointsDetail = (us) -> - - rolePoints = _.clone(_.filter($scope.project.roles, "computable"), true) - _.map rolePoints, (v, k) -> - val = $scope.pointsById[us.points[v.id]].value - val = "?" if not val? - v.points = val - - html = template({ - editable: editable - totalPoints: us.total_points - rolePoints: rolePoints - }) - $el.html(html) - - $scope.$watch $attrs.ngModel, (us) -> - if us? - renderUsPointsDetail(us) - - if editable - console.log "TODO" - - return {link:link, require:"ngModel"} - -module.directive("tgUsPointsDetail", USPointsDetailDirective) diff --git a/app/partials/issues-detail-edit.jade b/app/partials/issues-detail-edit.jade index 7cdb6484..13612d5b 100644 --- a/app/partials/issues-detail-edit.jade +++ b/app/partials/issues-detail-edit.jade @@ -24,7 +24,6 @@ block content div.user-story-tags(tg-tag-line, editable="true", ng-model="issue.tags") section.us-content - // TODO Placeholder should be a WYSIWYG with issue.description textarea(placeholder="Write a description of your issue", ng-model="issue.description", tg-markitup) // include views/modules/attachments @@ -36,14 +35,6 @@ block content section.watchers(tg-watchers, ng-model="issue.watchers", editable="true") section.us-detail-settings - //TODO: remove commented from issues-detail when copied to user-story-detail - //fieldset - // label.clickable.button.button-green(for="client-requirement", ng-class="{true:'active', false:''}[issue.client_requirement]") Client requirement - // input(ng-model="issue.client_requirement", type="checkbox", id="client-requirement", name="client-requirement") - //fieldset - // label.clickable.button.button-green(for="team-requirement", ng-class="{true:'active', false:''}[issue.team_requirement]") Team requirement - // input(ng-model="issue.team_requirement", type="checkbox", id="team-requirement", name="team-requirement") - a.button.button-gray.clickable(ng-show="!issue.is_blocked", ng-click="ctrl.block()") Block a.button.button-red(ng-click="ctrl.delete()", href="") Delete diff --git a/app/partials/us-detail.jade b/app/partials/us-detail.jade index a15197f3..e6db0aad 100644 --- a/app/partials/us-detail.jade +++ b/app/partials/us-detail.jade @@ -46,12 +46,6 @@ block content sidebar.menu-secondary.sidebar section.us-status(tg-us-status-detail, ng-model="us") - - div.us-detail-progress-bar - div.current-progress(style="width:{{ usProgress }}%") - span.tasks-completed {{ totalClosedTasks }}/{{ totalTasks}} tasks completed - ul.points-per-role(tg-us-points-detail, ng-model="us") - section.us-assigned-to(tg-assigned-to, ng-model="us") section.watchers(tg-watchers, ng-model="us.watchers") diff --git a/app/styles/components/buttons.scss b/app/styles/components/buttons.scss index ded99d77..dfa694ea 100755 --- a/app/styles/components/buttons.scss +++ b/app/styles/components/buttons.scss @@ -32,7 +32,8 @@ .button-green { background: $green-taiga; vertical-align: middle; - &:hover { + &:hover, + &.active { background: $fresh-taiga; } span { diff --git a/app/styles/layout/us-detail.scss b/app/styles/layout/us-detail.scss index 5fa9f463..618e7b8d 100644 --- a/app/styles/layout/us-detail.scss +++ b/app/styles/layout/us-detail.scss @@ -166,6 +166,7 @@ } .points-per-role { + position: relative; li { border-right: 1px solid $grayer; display: inline-block; @@ -194,6 +195,9 @@ text-overflow: ellipsis; white-space: nowrap; } + .pop-points-open { + @include popover(150px, '', 30px, '', ''); + } } .issue-data {