Merge pull request #89 from taigaio/us/675/convert-issue-to-us

US #675: Promote Issue to US
stable
Alejandro 2014-10-09 19:17:06 +02:00
commit 6f3c24d1e1
8 changed files with 108 additions and 10 deletions

View File

@ -1,5 +1,11 @@
# Changelog # # Changelog #
## 1.1.0 (2014-10-19)
### Features
- Promote an issue to a user story
## 1.0.0 (2014-10-07) ## 1.0.0 (2014-10-07)
### Misc ### Misc

View File

@ -50,12 +50,15 @@ class ConfirmService extends taiga.Service
el.off(".confirm-dialog") el.off(".confirm-dialog")
ask: (title, subtitle, lightboxSelector=".lightbox_confirm-delete") -> ask: (title, subtitle, message=null, lightboxSelector=".lightbox_confirm-delete") ->
el = angular.element(lightboxSelector) el = angular.element(lightboxSelector)
# Render content # Render content
el.find("h2.title").html(title) el.find("h2.title").html(title)
el.find("span.subtitle").html(subtitle) el.find("span.subtitle").html(subtitle)
if message
el.find("span.delete-question").html(message)
defered = @q.defer() defered = @q.defer()
# Assign event handlers # Assign event handlers

View File

@ -65,9 +65,12 @@ class IssueDetailController extends mixOf(taiga.Controller, taiga.PageMixin)
@location.replace() @location.replace()
return @q.reject(xhr) return @q.reject(xhr)
@scope.$on("attachment:create", => @rootscope.$broadcast("history:reload")) @scope.$on "attachment:create", => @rootscope.$broadcast("history:reload")
@scope.$on("attachment:edit", => @rootscope.$broadcast("history:reload")) @scope.$on "attachment:edit", => @rootscope.$broadcast("history:reload")
@scope.$on("attachment:delete", => @rootscope.$broadcast("history:reload")) @scope.$on "attachment:delete", => @rootscope.$broadcast("history:reload")
@scope.$on "promote-issue-to-us:success", =>
@rootscope.$broadcast("history:reload")
@.loadIssue()
loadProject: -> loadProject: ->
return @rs.projects.get(@scope.projectId).then (project) => return @rs.projects.get(@scope.projectId).then (project) =>
@ -362,3 +365,59 @@ IssueStatusDirective = () ->
return {link:link, require:"ngModel"} return {link:link, require:"ngModel"}
module.directive("tgIssueStatus", IssueStatusDirective) module.directive("tgIssueStatus", IssueStatusDirective)
#############################################################################
## Promote Issue to US button directive
#############################################################################
PromoteIssueToUsButtonDirective = ($rootScope, $repo, $confirm) ->
template = _.template("""
<a class="button button-gray clickable" tg-check-permission="add_us">
Promote to User Story
</a>
""") # TODO: i18n
link = ($scope, $el, $attrs, $model) ->
$el.on "click", "a", (event) ->
event.preventDefault()
issue = $model.$modelValue
title = "Promote this issue to a new user story" # TODO: i18n
message = "Are you sure you want to create a new US from this Issue?" # TODO: i18n
subtitle = issue.subject
$confirm.ask(title, subtitle, message).then (finish) =>
data = {
generated_from_issue: issue.id
project: issue.project,
subject: issue.subject
description: issue.description
tags: issue.tags
is_blocked: issue.is_blocked
blocked_note: issue.blocked_note
}
onSuccess = ->
finish()
$confirm.notify("success")
$rootScope.$broadcast("promote-issue-to-us:success")
onError = ->
finish(false)
$confirm.notify("error")
$repo.create("userstories", data).then(onSuccess, onError)
$scope.$on "$destroy", ->
$el.off()
return {
restrict: "AE"
require: "ngModel"
template: template
link: link
}
module.directive("tgPromoteIssueToUsButton", ["$rootScope", "$tgRepo", "$tgConfirm",
PromoteIssueToUsButtonDirective])

View File

@ -37,7 +37,6 @@ block content
section.watchers(tg-watchers, ng-model="issue", editable="true") section.watchers(tg-watchers, ng-model="issue", editable="true")
section.us-detail-settings section.us-detail-settings
a.button.button-green.clickable() Promote to User Story
a.button.button-gray.clickable(title="Click to block the issue", ng-show="!issue.is_blocked", ng-click="ctrl.block()") Block a.button.button-gray.clickable(title="Click to block the issue", ng-show="!issue.is_blocked", ng-click="ctrl.block()") Block
a.button.button-red(title="Click to delete the issue", tg-check-permission="delete_issue", ng-click="ctrl.delete()", href="") Delete a.button.button-red(title="Click to delete the issue", tg-check-permission="delete_issue", ng-click="ctrl.delete()", href="") Delete

View File

@ -17,9 +17,18 @@ block content
h2.us-title-text h2.us-title-text
span.us-number(tg-bo-ref="issue.ref") span.us-number(tg-bo-ref="issue.ref")
span.us-name(ng-bind="issue.subject") span.us-name(ng-bind="issue.subject")
p.us-related-task(ng-if="issue.generated_user_stories") This issue has been promoted to US:
a(ng-repeat="us in issue.generated_user_stories",
tg-check-permission="view_us", href="",
tg-bo-title="'#' + us.ref + ' ' + us.subject",
tg-nav="project-userstories-detail:project=project.slug, ref=us.ref")
span(tg-bo-ref="us.ref")
p.block-desc-container(ng-show="issue.is_blocked") p.block-desc-container(ng-show="issue.is_blocked")
span.block-description-title Blocked span.block-description-title Blocked
span.block-description(tg-bind-html="issue.blocked_note || 'This issue is blocked'") span.block-description(tg-bind-html="issue.blocked_note || 'This issue is blocked'")
div.issue-nav div.issue-nav
a.icon.icon-arrow-left(ng-show="previousUrl",href="{{ previousUrl }}", title="previous issue") a.icon.icon-arrow-left(ng-show="previousUrl",href="{{ previousUrl }}", title="previous issue")
a.icon.icon-arrow-right(ng-show="nextUrl", href="{{ nextUrl }}", title="next issue") a.icon.icon-arrow-right(ng-show="nextUrl", href="{{ nextUrl }}", title="next issue")
@ -35,3 +44,6 @@ block content
section.us-status(tg-issue-status, ng-model="issue") section.us-status(tg-issue-status, ng-model="issue")
section.us-assigned-to(tg-assigned-to, ng-model="issue") section.us-assigned-to(tg-assigned-to, ng-model="issue")
section.watchers(tg-watchers, ng-model="issue") section.watchers(tg-watchers, ng-model="issue")
section.us-detail-settings
tg-promote-issue-to-us-button(ng-model="issue")

View File

@ -15,7 +15,7 @@ block content
include views/modules/list-filters include views/modules/list-filters
include views/modules/issues-table include views/modules/issues-table
// Paginator is rended using js. // Paginator is rendered using js.
div.paginator.issues-paginator div.paginator.issues-paginator
div.lightbox.lightbox-select-user(tg-lb-assignedto) div.lightbox.lightbox-select-user(tg-lb-assignedto)

View File

@ -26,6 +26,12 @@ block content
span.us-number(tg-bo-ref="us.ref") span.us-number(tg-bo-ref="us.ref")
span.us-name(ng-bind="us.subject") span.us-name(ng-bind="us.subject")
p.us-related-task(ng-if="us.origin_issue") This US has been promoted from Issue
a(tg-check-permission="view_us", href="", title="Go to issue",
tg-nav="project-issues-detail:project=project.slug, ref=us.origin_issue.ref"
tg-bo-title="'#' + us.origin_issue.ref + ' ' + us.origin_issue.subject")
span(tg-bo-ref="us.origin_issue.ref")
p.block-desc-container(ng-show="us.is_blocked") p.block-desc-container(ng-show="us.is_blocked")
span.block-description-title Blocked span.block-description-title Blocked
span.block-description(tg-bind-html="us.blocked_note || 'This user story is blocked'") span.block-description(tg-bind-html="us.blocked_note || 'This user story is blocked'")

View File

@ -17,8 +17,16 @@
margin-bottom: .5rem; margin-bottom: .5rem;
} }
.us-number, .us-number,
.us-name { .us-name,
.us-related-task {
color: $white; color: $white;
a {
@include transition(color .3s linear);
color: $white;
&:hover {
color: $red-light;
}
}
} }
.unblock { .unblock {
@extend %bold; @extend %bold;
@ -35,6 +43,9 @@
} }
} }
} }
p {
margin-bottom: 0;
}
.us-edit-name-inner { .us-edit-name-inner {
@include table-flex(); @include table-flex();
} }
@ -68,16 +79,18 @@
margin-top: .5rem; margin-top: .5rem;
a { a {
@include transition(color .3s linear); @include transition(color .3s linear);
color: lighten($grayer, 30%); border-left: 1px solid $gray-light;
margin-left: .2rem; padding: 0 .2rem;
&:hover { &:hover {
color: $green-taiga; color: $green-taiga;
} }
&:first-child {
border: 0;
}
} }
} }
.block-desc-container { .block-desc-container {
@extend %small; @extend %small;
margin: 0 0 1.2rem;
} }
.block-description-title { .block-description-title {
@extend %bold; @extend %bold;