diff --git a/app/coffee/modules/common.coffee b/app/coffee/modules/common.coffee
index e71ffcc1..955861d0 100644
--- a/app/coffee/modules/common.coffee
+++ b/app/coffee/modules/common.coffee
@@ -98,16 +98,26 @@ module.factory("$selectedText", ["$window", "$document", SelectedText])
CheckPermissionDirective = (projectService) ->
render = ($el, project, permission) ->
- $el.removeClass('hidden') if project.get('my_permissions').indexOf(permission) > -1
+ if project && permission
+ $el.removeClass('hidden') if project.get('my_permissions').indexOf(permission) > -1
link = ($scope, $el, $attrs) ->
$el.addClass('hidden')
permission = $attrs.tgCheckPermission
- $scope.$watch ( () ->
+ unwatch = $scope.$watch () ->
return projectService.project
- ), () ->
- render($el, projectService.project, permission) if projectService.project
+ , () ->
+ return if !projectService.project
+
+ render($el, projectService.project, permission)
+ unwatch()
+
+ unObserve = $attrs.$observe "tgCheckPermission", (permission) ->
+ return if !permission
+
+ render($el, projectService.project, permission)
+ unObserve()
$scope.$on "$destroy", ->
$el.off()
diff --git a/app/coffee/modules/common/components.coffee b/app/coffee/modules/common/components.coffee
index adee97c1..e10451eb 100644
--- a/app/coffee/modules/common/components.coffee
+++ b/app/coffee/modules/common/components.coffee
@@ -185,13 +185,13 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template, $compile,
promise = $repo.save($model.$modelValue)
promise.then ->
- $confirm.notify("success")
watchers = _.map(watchers, (watcherId) -> $scope.usersById[watcherId])
renderWatchers(watchers)
$rootscope.$broadcast("object:updated")
promise.then null, ->
$model.$modelValue.revert()
+ $confirm.notify("error")
deleteWatcher = $qqueue.bindAdd (watcherIds) =>
item = $model.$modelValue.clone()
@@ -200,7 +200,6 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template, $compile,
promise = $repo.save($model.$modelValue)
promise.then ->
- $confirm.notify("success")
watchers = _.map(item.watchers, (watcherId) -> $scope.usersById[watcherId])
renderWatchers(watchers)
$rootscope.$broadcast("object:updated")
@@ -208,7 +207,6 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template, $compile,
item.revert()
$confirm.notify("error")
-
renderWatchers = (watchers) ->
ctx = {
watchers: watchers
@@ -235,12 +233,6 @@ WatchersDirective = ($rootscope, $confirm, $repo, $qqueue, $template, $compile,
deleteWatcher(watcherIds)
- $el.on "click", ".js-add-watcher", (event) ->
- event.preventDefault()
- return if not isEditable()
- $scope.$apply ->
- $rootscope.$broadcast("watcher:add", $model.$modelValue)
-
$scope.$on "watcher:added", (ctx, watcherId) ->
watchers = _.clone($model.$modelValue.watchers, false)
watchers.push(watcherId)
@@ -285,7 +277,6 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
promise = $repo.save($model.$modelValue)
promise.then ->
currentLoading.finish()
- $confirm.notify("success")
renderAssignedTo($model.$modelValue)
$rootscope.$broadcast("object:updated")
promise.then null, ->
@@ -295,13 +286,21 @@ AssignedToDirective = ($rootscope, $confirm, $repo, $loading, $qqueue, $template
return promise
- renderAssignedTo = (issue) ->
- assignedToId = issue?.assigned_to
- assignedTo = if assignedToId? then $scope.usersById[assignedToId] else null
+ renderAssignedTo = (assignedObject) ->
+ if assignedObject?.assigned_to_extra_info?
+ assignedTo = assignedObject?.assigned_to_extra_info
+ else
+ assignedTo = {
+ full_name_display: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED")
+ photo: "/#{window._version}/images/unnamed.png"
+ }
+
+ isIocaine = assignedObject?.is_iocaine
ctx = {
assignedTo: assignedTo
isEditable: isEditable()
+ isIocaine: isIocaine
}
html = $compile(template(ctx))($scope)
$el.html(html)
@@ -357,14 +356,14 @@ BlockButtonDirective = ($rootscope, $loading, $template) ->
return if not item
if isEditable()
- $el.find('.item-block').addClass('editable')
+ $el.find('.item-block').addClass('is-editable')
if item.is_blocked
- $el.find('.item-block').hide()
- $el.find('.item-unblock').show()
+ $el.find('.item-block').removeClass('is-active')
+ $el.find('.item-unblock').addClass('is-active')
else
- $el.find('.item-block').show()
- $el.find('.item-unblock').hide()
+ $el.find('.item-block').addClass('is-active')
+ $el.find('.item-unblock').removeClass('is-active')
$el.on "click", ".item-block", (event) ->
event.preventDefault()
@@ -711,13 +710,16 @@ ListItemTaskStatusDirective = ->
module.directive("tgListitemTaskStatus", ListItemTaskStatusDirective)
-ListItemAssignedtoDirective = ($template) ->
+ListItemAssignedtoDirective = ($template, $translate) ->
template = $template.get("common/components/list-item-assigned-to-avatar.html", true)
link = ($scope, $el, $attrs) ->
bindOnce $scope, "usersById", (usersById) ->
item = $scope.$eval($attrs.tgListitemAssignedto)
- ctx = {name: "Unassigned", imgurl: "/" + window._version + "/images/unnamed.png"}
+ ctx = {
+ name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
+ imgurl: "/#{window._version}/images/unnamed.png"
+ }
member = usersById[item.assigned_to]
if member
@@ -728,7 +730,7 @@ ListItemAssignedtoDirective = ($template) ->
return {link:link}
-module.directive("tgListitemAssignedto", ["$tgTemplate", ListItemAssignedtoDirective])
+module.directive("tgListitemAssignedto", ["$tgTemplate", "$translate", ListItemAssignedtoDirective])
ListItemIssueStatusDirective = ->
diff --git a/app/coffee/modules/common/estimation.coffee b/app/coffee/modules/common/estimation.coffee
index 4df473bd..6cf8417f 100644
--- a/app/coffee/modules/common/estimation.coffee
+++ b/app/coffee/modules/common/estimation.coffee
@@ -31,7 +31,7 @@ module = angular.module("taigaCommon")
## User story estimation directive (for Lightboxes)
#############################################################################
-LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $template, $compile) ->
+LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $template, $compile) ->
# Display the points of a US and you can edit it.
#
# Example:
@@ -72,14 +72,15 @@ LbUsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $
require: "ngModel"
}
-module.directive("tgLbUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgTemplate", "$compile", LbUsEstimationDirective])
+module.directive("tgLbUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgTemplate",
+ "$compile", LbUsEstimationDirective])
#############################################################################
## User story estimation directive
#############################################################################
-UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qqueue, $template, $compile) ->
+UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $qqueue, $template, $compile) ->
# Display the points of a US and you can edit it.
#
# Example:
@@ -120,8 +121,8 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $confirm, $qq
require: "ngModel"
}
-module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgConfirm", "$tgQqueue", "$tgTemplate", "$compile"
- UsEstimationDirective])
+module.directive("tgUsEstimation", ["$tgEstimationsService", "$rootScope", "$tgRepo", "$tgQqueue",
+ "$tgTemplate", "$compile", UsEstimationDirective])
#############################################################################
@@ -145,7 +146,6 @@ EstimationsService = ($template, $qqueue, $repo, $confirm, $q) ->
$qqueue.add () =>
onSuccess = =>
deferred.resolve()
- $confirm.notify("success")
onError = =>
$confirm.notify("error")
@@ -247,4 +247,5 @@ EstimationsService = ($template, $qqueue, $repo, $confirm, $q) ->
create: create
}
-module.factory("$tgEstimationsService", ["$tgTemplate", "$tgQqueue", "$tgRepo", "$tgConfirm", "$q", EstimationsService])
+module.factory("$tgEstimationsService", ["$tgTemplate", "$tgQqueue", "$tgRepo", "$tgConfirm",
+ "$q", EstimationsService])
diff --git a/app/coffee/modules/issues/detail.coffee b/app/coffee/modules/issues/detail.coffee
index c085242f..a4146c7a 100644
--- a/app/coffee/modules/issues/detail.coffee
+++ b/app/coffee/modules/issues/detail.coffee
@@ -282,11 +282,10 @@ IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $t
issue.status = statusId
currentLoading = $loading()
- .target($el.find(".level-name"))
+ .target($el)
.start()
onSuccess = ->
- $confirm.notify("success")
$model.$setViewValue(issue)
$rootScope.$broadcast("object:updated")
currentLoading.finish()
@@ -299,7 +298,7 @@ IssueStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $t
$repo.save(issue).then(onSuccess, onError)
- $el.on "click", ".status-data", (event) ->
+ $el.on "click", ".js-edit-status", (event) ->
event.preventDefault()
event.stopPropagation()
return if not isEditable()
@@ -373,7 +372,6 @@ IssueTypeButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $tem
.start()
onSuccess = ->
- $confirm.notify("success")
$model.$setViewValue(issue)
$rootScope.$broadcast("object:updated")
currentLoading.finish()
@@ -462,7 +460,6 @@ IssueSeverityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
.start()
onSuccess = ->
- $confirm.notify("success")
$model.$setViewValue(issue)
$rootScope.$broadcast("object:updated")
currentLoading.finish()
@@ -551,7 +548,6 @@ IssuePriorityButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue,
.start()
onSuccess = ->
- $confirm.notify("success")
$model.$setViewValue(issue)
$rootScope.$broadcast("object:updated")
currentLoading.finish()
diff --git a/app/coffee/modules/issues/list.coffee b/app/coffee/modules/issues/list.coffee
index e290c5b6..a0d1f251 100644
--- a/app/coffee/modules/issues/list.coffee
+++ b/app/coffee/modules/issues/list.coffee
@@ -778,7 +778,7 @@ module.directive("tgIssueStatusInlineEdition", ["$tgRepo", "$tgTemplate", "$root
## Issue assigned to Directive
#############################################################################
-IssueAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService) ->
+IssueAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) ->
template = _.template("""
<%- name %>
@@ -786,11 +786,15 @@ IssueAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService) ->
link = ($scope, $el, $attrs) ->
updateIssue = (issue) ->
- ctx = {name: "Unassigned", imgurl: "/" + window._version + "/images/unnamed.png"}
- member = $scope.usersById[issue.assigned_to]
+ ctx = {
+ name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
+ imgurl: "/#{window._version}/images/unnamed.png"
+ }
+
+ member = issue.assigned_to_extra_info
if member
- ctx.imgurl = member.photo
ctx.name = member.full_name_display
+ ctx.imgurl = member.photo
$el.find(".avatar").html(template(ctx))
$el.find(".issue-assignedto").attr('title', ctx.name)
@@ -822,5 +826,5 @@ IssueAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService) ->
return {link: link}
-module.directive("tgIssueAssignedToInlineEdition", ["$tgRepo", "$rootScope",
+module.directive("tgIssueAssignedToInlineEdition", ["$tgRepo", "$rootScope", "$translate"
IssueAssignedToInlineEditionDirective])
diff --git a/app/coffee/modules/kanban/main.coffee b/app/coffee/modules/kanban/main.coffee
index 46af5382..f4edca5e 100644
--- a/app/coffee/modules/kanban/main.coffee
+++ b/app/coffee/modules/kanban/main.coffee
@@ -527,7 +527,7 @@ module.directive("tgKanbanWipLimit", KanbanWipLimitDirective)
## Kanban User Directive
#############################################################################
-KanbanUserDirective = ($log, $compile) ->
+KanbanUserDirective = ($log, $compile, $translate) ->
template = _.template("""
class="not-clickable"<% } %>>
@@ -555,9 +555,17 @@ KanbanUserDirective = ($log, $compile) ->
render = (user) ->
if user is undefined
- ctx = {name: "Unassigned", imgurl: "/" + window._version + "/images/unnamed.png", clickable: clickable}
+ ctx = {
+ name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
+ imgurl: "/#{window._version}/images/unnamed.png",
+ clickable: clickable
+ }
else
- ctx = {name: user.full_name_display, imgurl: user.photo, clickable: clickable}
+ ctx = {
+ name: user.full_name_display,
+ imgurl: user.photo,
+ clickable: clickable
+ }
html = $compile(template(ctx))($scope)
$el.html(html)
@@ -588,4 +596,4 @@ KanbanUserDirective = ($log, $compile) ->
return {link: link, require:"ngModel"}
-module.directive("tgKanbanUserAvatar", ["$log", "$compile", KanbanUserDirective])
+module.directive("tgKanbanUserAvatar", ["$log", "$compile", "$translate", KanbanUserDirective])
diff --git a/app/coffee/modules/related-tasks.coffee b/app/coffee/modules/related-tasks.coffee
index fb2ce8da..3d777a74 100644
--- a/app/coffee/modules/related-tasks.coffee
+++ b/app/coffee/modules/related-tasks.coffee
@@ -241,7 +241,7 @@ RelatedTasksDirective = ($repo, $rs, $rootscope) ->
return {link: link}
module.directive("tgRelatedTasks", ["$tgRepo", "$tgResources", "$rootScope", RelatedTasksDirective])
-RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService) ->
+RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, $translate) ->
template = _.template("""
<%- name %>
@@ -249,7 +249,10 @@ RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService
link = ($scope, $el, $attrs) ->
updateRelatedTask = (task) ->
- ctx = {name: "Unassigned", imgurl: "/" + window._version + "/images/unnamed.png"}
+ ctx = {
+ name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
+ imgurl: "/" + window._version + "/images/unnamed.png"
+ }
member = $scope.usersById[task.assigned_to]
if member
ctx.imgurl = member.photo
@@ -287,4 +290,5 @@ RelatedTaskAssignedToInlineEditionDirective = ($repo, $rootscope, popoverService
return {link: link}
-module.directive("tgRelatedTaskAssignedToInlineEdition", ["$tgRepo", "$rootScope", RelatedTaskAssignedToInlineEditionDirective])
+module.directive("tgRelatedTaskAssignedToInlineEdition", ["$tgRepo", "$rootScope", "$translate",
+ RelatedTaskAssignedToInlineEditionDirective])
diff --git a/app/coffee/modules/taskboard/main.coffee b/app/coffee/modules/taskboard/main.coffee
index 44a216d3..757a0320 100644
--- a/app/coffee/modules/taskboard/main.coffee
+++ b/app/coffee/modules/taskboard/main.coffee
@@ -436,7 +436,7 @@ module.directive("tgTaskboardSquishColumn", ["$tgResources", TaskboardSquishColu
## Taskboard User Directive
#############################################################################
-TaskboardUserDirective = ($log) ->
+TaskboardUserDirective = ($log, $translate) ->
clickable = false
link = ($scope, $el, $attrs) ->
@@ -447,9 +447,17 @@ TaskboardUserDirective = ($log) ->
user = $scope.usersById[assigned_to]
if user is undefined
- _.assign($scope, {name: "Unassigned", imgurl: "/" + window._version + "/images/unnamed.png", clickable: clickable})
+ _.assign($scope, {
+ name: $translate.instant("COMMON.ASSIGNED_TO.NOT_ASSIGNED"),
+ imgurl: "/#{window._version}/images/unnamed.png",
+ clickable: clickable
+ })
else
- _.assign($scope, {name: user.full_name_display, imgurl: user.photo, clickable: clickable})
+ _.assign($scope, {
+ name: user.full_name_display,
+ imgurl: user.photo,
+ clickable: clickable
+ })
username_label.text($scope.name)
@@ -484,4 +492,4 @@ TaskboardUserDirective = ($log) ->
}
-module.directive("tgTaskboardUserAvatar", ["$log", TaskboardUserDirective])
+module.directive("tgTaskboardUserAvatar", ["$log", "$translate", TaskboardUserDirective])
diff --git a/app/coffee/modules/tasks/detail.coffee b/app/coffee/modules/tasks/detail.coffee
index c202bce5..b0c8f688 100644
--- a/app/coffee/modules/tasks/detail.coffee
+++ b/app/coffee/modules/tasks/detail.coffee
@@ -278,12 +278,11 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $co
task.status = status
currentLoading = $loading()
- .target($el.find(".level-name"))
+ .target($el)
.start()
onSuccess = ->
$model.$setViewValue(task)
- $confirm.notify("success")
$rootScope.$broadcast("object:updated")
currentLoading.finish()
@@ -293,7 +292,7 @@ TaskStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $co
$repo.save(task).then(onSuccess, onError)
- $el.on "click", ".status-data", (event) ->
+ $el.on "click", ".js-edit-status", (event) ->
event.preventDefault()
event.stopPropagation()
return if not isEditable()
@@ -327,17 +326,8 @@ module.directive("tgTaskStatusButton", ["$rootScope", "$tgRepo", "$tgConfirm", "
"$compile", "$translate", "$tgTemplate", TaskStatusButtonDirective])
-TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $compile) ->
- template = _.template("""
-
- """)
+TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue, $compile, $template) ->
+ template = $template.get("issue/iocaine-button.html", true)
link = ($scope, $el, $attrs, $model) ->
isEditable = ->
@@ -367,7 +357,6 @@ TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue
promise.then ->
$model.$setViewValue(task)
- $confirm.notify("success")
$rootscope.$broadcast("object:updated")
promise.then null, ->
@@ -395,4 +384,4 @@ TaskIsIocaineButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qqueue
}
module.directive("tgTaskIsIocaineButton", ["$rootScope", "$tgRepo", "$tgConfirm", "$tgLoading", "$tgQqueue",
- "$compile", TaskIsIocaineButtonDirective])
+ "$compile", "$tgTemplate", TaskIsIocaineButtonDirective])
diff --git a/app/coffee/modules/userstories/detail.coffee b/app/coffee/modules/userstories/detail.coffee
index 10f60741..08468dc8 100644
--- a/app/coffee/modules/userstories/detail.coffee
+++ b/app/coffee/modules/userstories/detail.coffee
@@ -277,54 +277,6 @@ UsStatusDisplayDirective = ($template, $compile) ->
module.directive("tgUsStatusDisplay", ["$tgTemplate", "$compile", UsStatusDisplayDirective])
-
-#############################################################################
-## User story related tasts progress splay Directive
-#############################################################################
-
-UsTasksProgressDisplayDirective = ($template, $compile) ->
- # Display a progress bar with the stats of completed tasks.
- #
- # Example:
- # tg-us-tasks-progress-display(ng-model="tasks")
- #
- # Requirements:
- # - Task object list (ng-model)
- # - scope.taskStatusById object
-
- link = ($scope, $el, $attrs) ->
- render = (tasks) ->
- totalTasks = tasks.length
- totalClosedTasks = _.filter(tasks, (task) => $scope.taskStatusById[task.status].is_closed).length
-
- progress = if totalTasks > 0 then 100 * totalClosedTasks / totalTasks else 0
-
- _.assign($scope, {
- totalTasks: totalTasks
- totalClosedTasks: totalClosedTasks
- progress: progress,
- style: {
- width: progress + "%"
- }
- })
-
- $scope.$watch $attrs.ngModel, (tasks) ->
- render(tasks) if tasks?
-
- $scope.$on "$destroy", ->
- $el.off()
-
- return {
- templateUrl: "us/us-task-progress.html"
- link: link
- restrict: "EA"
- require: "ngModel"
- scope: true
- }
-
-module.directive("tgUsTasksProgressDisplay", ["$tgTemplate", "$compile", UsTasksProgressDisplayDirective])
-
-
#############################################################################
## User story status button directive
#############################################################################
@@ -365,11 +317,10 @@ UsStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $temp
$.fn.popover().closeAll()
currentLoading = $loading()
- .target($el.find(".level-name"))
+ .target($el)
.start()
onSuccess = ->
- $confirm.notify("success")
$model.$setViewValue(us)
$rootScope.$broadcast("object:updated")
currentLoading.finish()
@@ -380,7 +331,7 @@ UsStatusButtonDirective = ($rootScope, $repo, $confirm, $loading, $qqueue, $temp
$repo.save(us).then(onSuccess, onError)
- $el.on "click", ".status-data", (event) ->
+ $el.on "click", ".js-edit-status", (event) ->
event.preventDefault()
event.stopPropagation()
return if not isEditable()
@@ -425,10 +376,6 @@ UsTeamRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $qq
return $scope.project.my_permissions.indexOf("modify_us") != -1
render = (us) ->
- if not canEdit() and not us.team_requirement
- $el.html("")
- return
-
ctx = {
canEdit: canEdit()
isRequired: us.team_requirement
@@ -489,10 +436,6 @@ UsClientRequirementButtonDirective = ($rootscope, $tgrepo, $confirm, $loading, $
return $scope.project.my_permissions.indexOf("modify_us") != -1
render = (us) ->
- if not canEdit() and not us.client_requirement
- $el.html("")
- return
-
ctx = {
canEdit: canEdit()
isRequired: us.client_requirement
diff --git a/app/locales/taiga/locale-en.json b/app/locales/taiga/locale-en.json
index 37455848..9bc7d330 100644
--- a/app/locales/taiga/locale-en.json
+++ b/app/locales/taiga/locale-en.json
@@ -24,6 +24,8 @@
"FROM": "from",
"TO": "to",
"CLOSE": "close",
+ "BLOCK": "Block this User Story if it has a dependency that can not be satisfied",
+ "UNBLOCK": "Unblock this User Story",
"BLOCKED_NOTE": "Why is this user story blocked?",
"BLOCKED_REASON": "Please explain the reason",
"GO_HOME": "Take me home",
@@ -36,6 +38,8 @@
"EXTERNAL_USER": "an external user",
"GENERIC_ERROR": "One of our Oompa Loompas says {{error}}.",
"IOCAINE_TEXT": "Feeling a bit overwhelmed by a task? Make sure others know about it by clicking on Iocaine when editing a task. It's possible to become immune to this (fictional) deadly poison by consuming small amounts over time just as it's possible to get better at what you do by occasionally taking on extra challenges!",
+ "CLIENT_REQUIREMENT": "Client requirement is new requirement that was not previously expected and it is required to be part of the project",
+ "TEAM_REQUIREMENT": "Team requirement is a requirement that must exist in the project but should have no cost for the client",
"CAPSLOCK_WARNING": "Be careful! You're writing with capital letters and this input is case sensitive.",
"FORM_ERRORS": {
"DEFAULT_MESSAGE": "This value seems to be invalid.",
@@ -150,6 +154,7 @@
"OPEN": "Open"
},
"WATCHERS": {
+ "WATCHERS": "Watchers",
"ADD": "Add watchers",
"TITLE_ADD": "Add a project member to the watchers list",
"DELETE": "Delete watcher",
diff --git a/app/modules/components/watch-button/watch-button-ticket.jade b/app/modules/components/watch-button/watch-button-ticket.jade
new file mode 100644
index 00000000..e54d36fd
--- /dev/null
+++ b/app/modules/components/watch-button/watch-button-ticket.jade
@@ -0,0 +1,37 @@
+div.ticket-watch-title(
+ title="{{ 'COMMON.WATCH_BUTTON.COUNTER_TITLE'|translate:{total:vm.item.watchers.length||0}:'messageformat' }}",
+ tg-loading="vm.loading"
+) {{ vm.item.watchers.length }} {{'COMMON.WATCHERS.WATCHERS' | translate}}
+
+div.ticket-watch-inner
+ a.ticket-watch-button(
+ href=""
+ title="{{ 'COMMON.WATCH_BUTTON.BUTTON_TITLE' | translate }}"
+ ng-if="::vm.user"
+ ng-click="vm.toggleWatch()"
+ ng-class="{'active': vm.item.is_watcher, 'is-hover': vm.item.is_watcher && vm.isMouseOver}"
+ ng-mouseover="vm.showTextWhenMouseIsOver()"
+ ng-mouseleave="vm.showTextWhenMouseIsLeave()"
+ )
+ span.track-icon
+ include ../../../svg/watch.svg
+ span(
+ ng-if="!vm.item.is_watcher",
+ translate="COMMON.WATCH_BUTTON.WATCH"
+ )
+ span(
+ ng-if="vm.item.is_watcher && !vm.isMouseOver",
+ translate="COMMON.WATCH_BUTTON.WATCHING"
+ )
+ span(
+ ng-if="vm.item.is_watcher && vm.isMouseOver",
+ translate="COMMON.WATCH_BUTTON.UNWATCH"
+ )
+
+ a.add-watcher(
+ href=""
+ title="{{'COMMON.WATCHERS.TITLE_ADD' | translate}}"
+ ng-click="vm.openWatchers()"
+ tg-check-permission="{{vm.getPerms()}}"
+ )
+ span + {{'COMMON.WATCHERS.ADD' | translate}}
diff --git a/app/modules/components/watch-button/watch-button.controller.coffee b/app/modules/components/watch-button/watch-button.controller.coffee
index 39b16f57..99514424 100644
--- a/app/modules/components/watch-button/watch-button.controller.coffee
+++ b/app/modules/components/watch-button/watch-button.controller.coffee
@@ -20,9 +20,10 @@
class WatchButtonController
@.$inject = [
"tgCurrentUserService",
+ "$rootScope"
]
- constructor: (@currentUserService) ->
+ constructor: (@currentUserService, @rootScope) ->
@.user = @currentUserService.getUser()
@.isMouseOver = false
@.loading = false
@@ -33,6 +34,22 @@ class WatchButtonController
showTextWhenMouseIsLeave: ->
@.isMouseOver = false
+ openWatchers: ->
+ @rootScope.$broadcast("watcher:add", @.item)
+
+ getPerms: ->
+ return "" if !@.item
+
+ name = @.item._name
+
+ perms = {
+ userstories: 'modify_us',
+ issues: 'modify_issue',
+ tasks: 'modify_task'
+ }
+
+ return perms[name]
+
toggleWatch: ->
@.loading = true
diff --git a/app/modules/components/watch-button/watch-button.controller.spec.coffee b/app/modules/components/watch-button/watch-button.controller.spec.coffee
index db06465b..41e95efb 100644
--- a/app/modules/components/watch-button/watch-button.controller.spec.coffee
+++ b/app/modules/components/watch-button/watch-button.controller.spec.coffee
@@ -100,3 +100,24 @@ describe "WatchButton", ->
expect(ctrl.loading).to.be.false;
done()
+
+
+ it "get permissions", () ->
+ $scope = $rootScope.$new()
+
+ ctrl = $controller("WatchButton", $scope, {
+ item: {_name: 'tasks'}
+ })
+
+ perm = ctrl.getPerms()
+ expect(perm).to.be.equal('modify_task')
+
+ ctrl.item = {_name: 'issues'}
+
+ perm = ctrl.getPerms()
+ expect(perm).to.be.equal('modify_issue')
+
+ ctrl.item = {_name: 'userstories'}
+
+ perm = ctrl.getPerms()
+ expect(perm).to.be.equal('modify_us')
diff --git a/app/modules/components/watch-button/watch-button.directive.coffee b/app/modules/components/watch-button/watch-button.directive.coffee
index 12a9ac7b..a5797950 100644
--- a/app/modules/components/watch-button/watch-button.directive.coffee
+++ b/app/modules/components/watch-button/watch-button.directive.coffee
@@ -27,7 +27,8 @@ WatchButtonDirective = ->
onUnwatch: "="
}
controllerAs: "vm",
- templateUrl: "components/watch-button/watch-button.html",
+ templateUrl: (item, attributes) ->
+ return "components/watch-button/watch-button-"+attributes.environment+".html"
}
angular.module("taigaComponents").directive("tgWatchButton", WatchButtonDirective)
diff --git a/app/modules/navigation-bar/navigation-bar.scss b/app/modules/navigation-bar/navigation-bar.scss
index 469ecb8d..440784c0 100644
--- a/app/modules/navigation-bar/navigation-bar.scss
+++ b/app/modules/navigation-bar/navigation-bar.scss
@@ -32,7 +32,9 @@ $dropdown-width: 350px;
}
svg {
height: 1.6rem;
+ max-height: 1.6rem;
max-width: 2rem;
+ width: 1.6rem;
}
path {
fill: $white;
@@ -79,7 +81,9 @@ $dropdown-width: 350px;
}
svg {
height: 1.2rem;
+ max-height: 1.2rem;
max-width: 1.2rem;
+ width: 1.2rem;
path {
fill: $top-icon-color;
transition: all .2s;
diff --git a/app/partials/common/components/assigned-to.jade b/app/partials/common/components/assigned-to.jade
index 7ad68ab3..79ae8748 100644
--- a/app/partials/common/components/assigned-to.jade
+++ b/app/partials/common/components/assigned-to.jade
@@ -1,6 +1,10 @@
<% if (assignedTo) { %>
-.user-avatar
+.user-avatar(class!="<% if(isIocaine){ %> is-iocaine <% }; %>")
img(src!="<%- assignedTo.photo %>", alt!="<%- assignedTo.full_name_display %>")
+ <% if(isIocaine){ %>
+ .iocaine-symbol(title="{{ 'TASK.TITLE_ACTION_IOCAINE' | translate }}")
+ include ../../../svg/iocaine.svg
+ <% }; %>
<% } %>
.assigned-to
@@ -9,11 +13,7 @@
a(href="" title="{{ 'COMMON.ASSIGNED_TO.TITLE_ACTION_EDIT_ASSIGNMENT'|translate }}",
class!="user-assigned <% if(isEditable){ %>editable<% }; %>")
span.assigned-name
- <% if (assignedTo) { %>
<%- assignedTo.full_name_display %>
- <% } else { %>
- | {{ 'COMMON.ASSIGNED_TO.NOT_ASSIGNED'|translate }}
- <% } %>
<% if(isEditable){ %>
span.icon.icon-arrow-bottom
<% }; %>
diff --git a/app/partials/common/components/block-button.jade b/app/partials/common/components/block-button.jade
index 8dc4e055..631d288c 100644
--- a/app/partials/common/components/block-button.jade
+++ b/app/partials/common/components/block-button.jade
@@ -1,4 +1,10 @@
-a(href="#", class="button button-gray item-block")
- span(translate="COMMON.BLOCK")
-a(href="#", class="button button-red item-unblock")
- span(translate="COMMON.UNBLOCK")
+a.button-gray.item-block(
+ href=""
+ title="{{ 'COMMON.BLOCK' | translate }}"
+)
+ include ../../../svg/lock.svg
+a.button-red.item-unblock(
+ href=""
+ title="{{ 'COMMON.UNBLOCK' | translate }}"
+)
+ include ../../../svg/unlock.svg
diff --git a/app/partials/common/components/created-by.jade b/app/partials/common/components/created-by.jade
index 3689afef..8486d0fa 100644
--- a/app/partials/common/components/created-by.jade
+++ b/app/partials/common/components/created-by.jade
@@ -1,9 +1,17 @@
-.user-avatar
- a(href="{{url}}", title="{{owner.full_name_display}}")
- img(src="{{owner.photo}}", alt="{{owner.full_name_display}}")
-
.created-by
- a(href="{{url}}", title="{{owner.full_name_display}}")
- span.created-title(translate="COMMON.CREATED_BY", translate-values="{ 'fullDisplayName': owner.full_name_display}")
- span.created-date
- | {{date}}
+ a.created-title(
+ href="{{url}}"
+ title="{{owner.full_name_display}}"
+ translate="COMMON.CREATED_BY"
+ translate-values="{ 'fullDisplayName': owner.full_name_display}"
+ )
+ .created-date {{date}}
+.user-avatar
+ a(
+ href="{{url}}"
+ title="{{owner.full_name_display}}"
+ )
+ img(
+ src="{{owner.photo}}"
+ alt="{{owner.full_name_display}}"
+ )
diff --git a/app/partials/common/components/delete-button.jade b/app/partials/common/components/delete-button.jade
index cc325950..22f6ee5b 100644
--- a/app/partials/common/components/delete-button.jade
+++ b/app/partials/common/components/delete-button.jade
@@ -1,2 +1,5 @@
-a.button-red.button-delete(href="")
- span(translate="COMMON.DELETE")
+a.button-red.button-delete(
+ href=""
+ title="{{ 'COMMON.DELETE' | translate }}"
+)
+ include ../../../svg/trash.svg
diff --git a/app/partials/common/components/status-display.jade b/app/partials/common/components/status-display.jade
index 098ffa32..553ea3b1 100644
--- a/app/partials/common/components/status-display.jade
+++ b/app/partials/common/components/status-display.jade
@@ -3,5 +3,3 @@ span(translate="COMMON.STATUS.CLOSED")
<% } else { %>
span(translate="COMMON.STATUS.OPEN")
<% } %>
-span(class="detail-status", style!="color:<%- status.color %>")
- | <%- status.name %>
diff --git a/app/partials/common/components/watchers.jade b/app/partials/common/components/watchers.jade
index 31e4ea94..fcbe398d 100644
--- a/app/partials/common/components/watchers.jade
+++ b/app/partials/common/components/watchers.jade
@@ -18,12 +18,3 @@
<% }; %>
<% } %>
<% }); %>
-
-<% if(isEditable){ %>
-a.add-watcher.js-add-watcher(
- href=""
- title="{{'COMMON.WATCHERS.TITLE_ADD' | translate}}"
-)
- span.icon.icon-plus
- span(translate="COMMON.WATCHERS.ADD")
-<% }; %>
diff --git a/app/partials/common/estimation/us-estimation-points-per-role.jade b/app/partials/common/estimation/us-estimation-points-per-role.jade
index 904d6b4a..86bf489c 100644
--- a/app/partials/common/estimation/us-estimation-points-per-role.jade
+++ b/app/partials/common/estimation/us-estimation-points-per-role.jade
@@ -1,9 +1,12 @@
ul.points-per-role
+ <% _.each(roles, function(role) { %>
+ li.ticket-role-points.total(class!="<% if(editable){ %>clickable<% } %>", data-role-id!="<%- role.id %>", title!="<%- role.name %>")
+ span.points
+ <%- role.points %>
+ span.icon-arrow-bottom
+ span.role
+ <%- role.name %>
+ <% }); %>
li.ticket-role-points.total
span.points <%- totalPoints %>
span.role(translate="US.TOTAL_POINTS")
- <% _.each(roles, function(role) { %>
- li.ticket-role-points(class!="total <% if(editable){ %>clickable<% } %>", data-role-id!="<%- role.id %>", title!="<%- role.name %>")
- span.points <%- role.points %>
- span.role <%- role.name %>
- <% }); %>
diff --git a/app/partials/common/tag/tag-line.jade b/app/partials/common/tag/tag-line.jade
index c7df1c3a..d6bc320a 100644
--- a/app/partials/common/tag/tag-line.jade
+++ b/app/partials/common/tag/tag-line.jade
@@ -4,4 +4,4 @@ a(href="#", class="add-tag hidden", title="{{'COMMON.TAGS.ADD' | translate}}")
span.add-tag-text(translate="COMMON.TAGS.ADD")
input(type="text", placeholder="{{'COMMON.TAGS.PLACEHOLDER' | translate}}", class="tag-input hidden")
-a(href="", title="{{'COMMON.SAVE' | translate}}", class="save icon icon-floppy hidden")
\ No newline at end of file
+a(href="", title="{{'COMMON.SAVE' | translate}}", class="save icon icon-floppy hidden")
diff --git a/app/partials/issue/iocaine-button.jade b/app/partials/issue/iocaine-button.jade
new file mode 100644
index 00000000..fecc54d9
--- /dev/null
+++ b/app/partials/issue/iocaine-button.jade
@@ -0,0 +1,11 @@
+fieldset(title="{{ 'TASK.TITLE_ACTION_IOCAINE' | translate }}")
+ label.button-gray.is-iocaine(
+ for="is-iocaine"
+ class!="<% if(isEditable){ %>is-editable<% }; %> <% if(isIocaine){ %>active<% }; %>"
+ )
+ include ../../svg/iocaine.svg
+ input(
+ type="checkbox"
+ id="is-iocaine"
+ name="is-iocaine"
+ )
diff --git a/app/partials/issue/issues-detail.jade b/app/partials/issue/issues-detail.jade
index 06e00bc0..da3a33e5 100644
--- a/app/partials/issue/issues-detail.jade
+++ b/app/partials/issue/issues-detail.jade
@@ -57,8 +57,9 @@ div.wrapper(
tg-bo-href="nextUrl"
title="{{'ISSUES.TITLE_NEXT_ISSUE' | translate}}"
)
-
- div.tags-block(tg-tag-line, ng-model="issue", required-perm="modify_issue")
+ .subheader
+ div.tags-block(tg-tag-line, ng-model="issue", required-perm="modify_issue")
+ tg-created-by-display.ticket-created-by(ng-model="issue")
section.duty-content(tg-editable-description, tg-editable-wysiwyg, ng-model="issue", required-perm="modify_issue")
@@ -79,35 +80,49 @@ div.wrapper(
tg-history(ng-model="issue", type="issue")
sidebar.menu-secondary.sidebar.ticket-data
- section.status
- .ticket-title(tg-issue-status-display, ng-model="issue")
- tg-created-by-display.ticket-created-by(ng-model="issue")
+
+ .ticket-header
+ span.ticket-title(
+ tg-issue-status-display
+ ng-model="issue"
+ )
+ span.detail-status(
+ tg-issue-status-button
+ ng-model="issue"
+ )
+
+ //tg-created-by-display.ticket-created-by(ng-model="issue")
+
div.ticket-data-container
div.ticket-status(tg-issue-type-button, ng-model="issue")
div.ticket-status(tg-issue-severity-button, ng-model="issue")
div.ticket-status(tg-issue-priority-button, ng-model="issue")
- div.ticket-status(tg-issue-status-button, ng-model="issue")
section.ticket-assigned-to(tg-assigned-to, ng-model="issue", required-perm="modify_issue")
- section.track-buttons-container.ticket-track-buttons
-
- div.watch-button
- tg-watch-button(
- item="issue"
- on-watch="ctrl.onWatch"
- on-unwatch="ctrl.onUnwatch"
- )
-
+ section.ticket-watch-buttons
+ div.ticket-watch(
+ tg-watch-button
+ item="issue"
+ data-environment="ticket"
+ on-watch="ctrl.onWatch"
+ on-unwatch="ctrl.onUnwatch"
+ )
div.ticket-watchers(
tg-watchers
ng-model="issue"
- required-perm="modify_issue"
+ required-perm="modify_us"
)
section.ticket-detail-settings
- tg-promote-issue-to-us-button(tg-check-permission="add_us", ng-model="issue")
- tg-block-button(tg-check-permission="modify_issue", ng-model="issue")
+ tg-promote-issue-to-us-button(
+ tg-check-permission="add_us",
+ ng-model="issue"
+ )
+ tg-block-button(
+ tg-check-permission="modify_issue",
+ ng-model="issue"
+ )
tg-delete-button(
tg-check-permission="delete_issue",
on-delete-title="{{'ISSUES.ACTION_DELETE' | translate}}",
diff --git a/app/partials/issue/issues-status-button.jade b/app/partials/issue/issues-status-button.jade
index 6d56fae8..37651385 100644
--- a/app/partials/issue/issues-status-button.jade
+++ b/app/partials/issue/issues-status-button.jade
@@ -1,15 +1,20 @@
-div(class!="status-data <% if(editable){ %>clickable<% }%>")
- span(class="level", style!="background-color:<%- status.color %>")
- span(class="status-status") <%- status.name %>
+span.detail-status-inner.js-edit-status(
+ class!="<% if(editable){ %>clickable<% }%>"
+ style!="background-color:<%- status.color %>"
+ ng-click="editStatus()"
+)
+ span <%- status.name %>
<% if(editable){ %>
- span(class="icon icon-arrow-bottom")
- <% } %>
- span(class="level-name", translate="COMMON.FIELDS.STATUS")
-
- ul(class="popover pop-status")
+ span.icon.icon-arrow-bottom
+ <% }%>
+
+ ul.pop-status
<% _.each(statuses, function(st) { %>
li
- a(href="", class="status", title!="<%- st.name %>",
- data-status-id!="<%- st.id %>")
+ a.status(
+ href=""
+ title!="<%- st.name %>"
+ data-status-id!="<%- st.id %>"
+ )
| <%- st.name %>
<% }); %>
diff --git a/app/partials/issue/promote-issue-to-us-button.jade b/app/partials/issue/promote-issue-to-us-button.jade
index 6d56172b..6eafe624 100644
--- a/app/partials/issue/promote-issue-to-us-button.jade
+++ b/app/partials/issue/promote-issue-to-us-button.jade
@@ -1,2 +1,2 @@
-a(class="button button-gray editable", tg-check-permission="add_us")
- span(translate="ISSUES.ACTION_PROMOTE_TO_US")
+a.promote-button.is-editable(tg-check-permission="add_us")
+ include ../../svg/promote.svg
diff --git a/app/partials/task/task-detail.jade b/app/partials/task/task-detail.jade
index c8e7dfb6..f9570518 100644
--- a/app/partials/task/task-detail.jade
+++ b/app/partials/task/task-detail.jade
@@ -72,8 +72,9 @@ div.wrapper(
tg-bo-href="nextUrl"
title="{{'TASK.NEXT' | translate}}"
)
-
- div.tags-block(tg-tag-line, ng-model="task", required-perm="modify_task")
+ .subheader
+ div.tags-block(tg-tag-line, ng-model="task", required-perm="modify_task")
+ tg-created-by-display.ticket-created-by(ng-model="task")
section.duty-content(tg-editable-description, tg-editable-wysiwyg, ng-model="task", required-perm="modify_task")
@@ -95,29 +96,30 @@ div.wrapper(
sidebar.menu-secondary.sidebar.ticket-data
- section.status
-
- .ticket-title(tg-task-status-display, ng-model="task")
-
- .ticket-created-by(tg-created-by-display, ng-model="task")
-
- .ticket-data-container
- .ticket-status(tg-task-status-button, ng-model="task")
+ .ticket-header
+ span.ticket-title(
+ tg-task-status-display
+ ng-model="task"
+ )
+ span.detail-status(
+ tg-task-status-button
+ ng-model="task"
+ )
section.ticket-assigned-to(tg-assigned-to, ng-model="task", required-perm="modify_task")
- section.track-buttons-container.ticket-track-buttons
- div.watch-button
- tg-watch-button(
- item="task"
- on-watch="ctrl.onWatch"
- on-unwatch="ctrl.onUnwatch"
- )
-
+ section.ticket-watch-buttons
+ div.ticket-watch(
+ tg-watch-button
+ item="task"
+ data-environment="ticket"
+ on-watch="ctrl.onWatch"
+ on-unwatch="ctrl.onUnwatch"
+ )
div.ticket-watchers(
- tg-watchers,
- ng-model="task",
- required-perm="modify_task"
+ tg-watchers
+ ng-model="task"
+ required-perm="modify_us"
)
section.ticket-detail-settings
diff --git a/app/partials/us/us-client-requirement-button.jade b/app/partials/us/us-client-requirement-button.jade
index dc269cbc..b8d7a506 100644
--- a/app/partials/us/us-client-requirement-button.jade
+++ b/app/partials/us/us-client-requirement-button.jade
@@ -1,4 +1,11 @@
-label(for="client-requirement",
- class!="button button-gray client-requirement <% if(canEdit){ %>editable<% }; %> <% if(isRequired){ %>active<% }; %>", translate="US.FIELDS.CLIENT_REQUIREMENT")
-
-input(type="checkbox", id="client-requirement", name="client-requirement")
\ No newline at end of file
+label.button-gray.client-requirement(
+ for="client-requirement"
+ class!="<% if(canEdit){ %>is-editable<% }; %> <% if(isRequired){ %>active<% }; %>"
+ title="{{ 'COMMON.CLIENT_REQUIREMENT' | translate }}"
+)
+ include ../../svg/client-requirement.svg
+input(
+ type="checkbox"
+ id="client-requirement"
+ name="client-requirement"
+)
diff --git a/app/partials/us/us-detail.jade b/app/partials/us/us-detail.jade
index 1b845b7a..65b6f893 100644
--- a/app/partials/us/us-detail.jade
+++ b/app/partials/us/us-detail.jade
@@ -65,8 +65,9 @@ div.wrapper(
tg-bo-href="nextUrl"
title="{{'US.NEXT' | translate}}"
)
-
- div.tags-block(tg-tag-line, ng-model="us", required-perm="modify_us")
+ .subheader
+ .tags-block(tg-tag-line, ng-model="us", required-perm="modify_us")
+ tg-created-by-display.ticket-created-by(ng-model="us")
section.duty-content(tg-editable-description, tg-editable-wysiwyg, ng-model="us", required-perm="modify_us")
@@ -92,24 +93,18 @@ div.wrapper(
)
sidebar.menu-secondary.sidebar.ticket-data
- section
- div.ticket-title(
+
+ section.ticket-header
+ span.ticket-title(
tg-us-status-display
ng-model="us"
)
+ span.detail-status(
+ tg-us-status-button
+ ng-model="us"
+ )
- tg-created-by-display.ticket-created-by(ng-model="us")
-
- //div.ticket-detail-progress-bar(tg-us-tasks-progress-display, ng-model="tasks")
-
- div.ticket-data-container
- div.ticket-status(
- tg-us-status-button
- ng-model="us"
- )
-
- section.ticket-estimation
- tg-us-estimation(ng-model="us")
+ tg-us-estimation.ticket-estimation(ng-model="us")
section.ticket-assigned-to(
tg-assigned-to
@@ -117,20 +112,21 @@ div.wrapper(
required-perm="modify_us"
)
- section.track-buttons-container.ticket-track-buttons
- div.watch-button
- tg-watch-button(
- item="us"
- on-watch="ctrl.onWatch"
- on-unwatch="ctrl.onUnwatch"
- )
-
+ section.ticket-watch-buttons
+ div.ticket-watch(
+ tg-watch-button
+ item="us"
+ data-environment="ticket"
+ on-watch="ctrl.onWatch"
+ on-unwatch="ctrl.onUnwatch"
+ )
div.ticket-watchers(
tg-watchers
ng-model="us"
required-perm="modify_us"
)
+
section.ticket-detail-settings
tg-us-team-requirement-button(ng-model="us")
tg-us-client-requirement-button(ng-model="us")
diff --git a/app/partials/us/us-status-button.jade b/app/partials/us/us-status-button.jade
index 7a3ba3b5..64f9caaf 100644
--- a/app/partials/us/us-status-button.jade
+++ b/app/partials/us/us-status-button.jade
@@ -1,14 +1,19 @@
-div(class!="status-data <% if(editable){ %>clickable<% }%>")
- span.level(style!="background-color:<%- status.color %>")
- span.status-status <%- status.name %>
+span.detail-status-inner.js-edit-status(
+ class!="<% if(editable){ %>clickable<% }%>"
+ style!="background-color:<%- status.color %>"
+)
+ span <%- status.name %>
<% if(editable){ %>
span.icon.icon-arrow-bottom
<% }%>
- span.level-name(translate="COMMON.FIELDS.STATUS")
- ul.popover.pop-status
+ ul.pop-status.popover
<% _.each(statuses, function(st) { %>
li
- a(href="", class="status", title!="<%- st.name %>", data-status-id!="<%- st.id %>")
+ a.status(
+ href=""
+ title!="<%- st.name %>"
+ data-status-id!="<%- st.id %>"
+ )
| <%- st.name %>
<% }); %>
diff --git a/app/partials/us/us-task-progress.jade b/app/partials/us/us-task-progress.jade
deleted file mode 100644
index df2f8b7c..00000000
--- a/app/partials/us/us-task-progress.jade
+++ /dev/null
@@ -1,2 +0,0 @@
-.current-progress(ng-style='style')
-div.tasks-completed(translate="US.TASK_COMPLETED", translate-values='{ totalTasks: totalTasks, totalClosedTasks: totalClosedTasks}')
diff --git a/app/partials/us/us-team-requirement-button.jade b/app/partials/us/us-team-requirement-button.jade
index e1520364..e34338b1 100644
--- a/app/partials/us/us-team-requirement-button.jade
+++ b/app/partials/us/us-team-requirement-button.jade
@@ -1,3 +1,12 @@
-label(for="team-requirement", class!="button button-gray team-requirement <% if(canEdit){ %>editable<% }; %> <% if(isRequired){ %>active<% }; %>", translate="US.FIELDS.TEAM_REQUIREMENT")
+label.button-gray.team-requirement(
+ for="team-requirement"
+ class!=" <% if(canEdit){ %>is-editable<% }; %> <% if(isRequired){ %>active<% }; %>"
+ title="{{ 'COMMON.TEAM_REQUIREMENT' | translate }}"
+)
+ include ../../svg/team-requirement.svg
-input(type="checkbox", id="team-requirement", name="team-requirement")
\ No newline at end of file
+input(
+ type="checkbox"
+ id="team-requirement"
+ name="team-requirement"
+)
diff --git a/app/styles/components/created-by.scss b/app/styles/components/created-by.scss
index 734bd5f9..60d6470a 100644
--- a/app/styles/components/created-by.scss
+++ b/app/styles/components/created-by.scss
@@ -1,29 +1,45 @@
.ticket-created-by {
display: flex;
- margin-bottom: 1rem;
- margin-top: .5rem;
- position: relative;
+ justify-content: flex-end;
+ @include breakpoint(laptop) {
+ justify-content: flex-start;
+ margin-bottom: .5rem;
+ }
.user-avatar {
- flex-basis: 3rem;
+ flex-basis: 2rem;
flex-grow: 0;
- margin-right: .5rem;
+ margin-left: .5rem;
+ @include breakpoint(laptop) {
+ margin-left: 0;
+ margin-right: .5rem;
+ order: 1;
+ }
img {
width: 100%;
}
}
.created-by {
+ @include breakpoint(laptop) {
+ order: 2;
+ }
.created-title,
.created-date {
@extend %light;
@extend %small;
color: $gray;
display: block;
- line-height: 1.5;
+ text-align: right;
+ @include breakpoint(laptop) {
+ text-align: left;
+ }
}
.created-title {
color: $primary;
- &.editable {
- cursor: pointer;
+ }
+ .created-date {
+ margin-left: .5rem;
+ @include breakpoint(laptop) {
+ margin-left: 0;
}
}
}
diff --git a/app/styles/components/estimation.scss b/app/styles/components/estimation.scss
index 3f50666d..fcc98acd 100644
--- a/app/styles/components/estimation.scss
+++ b/app/styles/components/estimation.scss
@@ -1,48 +1,56 @@
-%estimation {
+@mixin estimation {
.points-per-role {
display: flex;
- flex-wrap: wrap;
- justify-content: center;
+ flex-direction: column;
}
.ticket-role-points {
- background: rgba($gray-light, .1);
- border-radius: 2px;
- color: rgba($grayer, .3);
- flex-basis: 20%;
- flex-grow: 1;
- flex-shrink: 0;
- margin: .1rem;
- padding: .5rem 0 .1rem;
+ background: rgba($gray-light, .2);
+ color: $gray-light;
+ display: flex;
+ flex: 1;
+ justify-content: space-between;
+ margin-bottom: .1rem;
+ padding: .5rem 1rem;
position: relative;
- text-align: center;
transition: color .3s linear;
- &.active {
- background: rgba($primary-light, .9);
- color: $whitish;
- }
- &:first-child {
- background: rgba($grayer, .25);
- border-radius: 0;
- color: $whitish;
+ &.clickable {
+ &:hover,
+ &.active {
+ background: rgba($primary-light, .9);
+ color: $whitish;
+ .points,
+ .role,
+ .icon-arrow-bottom {
+ color: $whitish;
+ }
+ }
}
&:last-child {
- border: 0;
+ background: rgba($primary-dark, .5);
+ border-bottom: 0;
+ color: $whitish;
+ .points,
+ .role,
+ .icon-arrow-bottom {
+ @extend %text;
+ color: $whitish;
+ }
+ }
+ .icon-arrow-bottom {
+ color: $gray-light;
+ margin-left: .25rem;
+ vertical-align: middle;
}
.points {
- @extend %larger;
- @extend %text;
- display: block;
- text-align: center;
+ @extend %light;
+ color: $grayer;
}
.role {
- @extend %small;
- @include ellipsis(90%);
- display: inline-block;
- text-align: center;
+ @extend %light;
}
}
.popover {
- @include popover(200px, $top: 105%, $left: 35%, $arrow-width: 10px, $arrow-top: -5px, $arrow-left: 10px, $arrow-height: 10px);
+ @include popover(200px, $top: 100%, $left: .5rem, $arrow-width: 10px, $arrow-top: -5px, $arrow-left: 10px, $arrow-height: 10px);
li {
display: inline-block;
width: 23%;
@@ -57,11 +65,11 @@
}
}
&.fix {
- @include popover(200px, $top: 105%, $left: -160px, $arrow-width: 10px, $arrow-top: -5px, $arrow-left: 90%, $arrow-height: 10px);
+ @include popover(200px, $top: 100%, $left: -160px, $arrow-width: 10px, $arrow-top: -5px, $arrow-left: 90%, $arrow-height: 10px);
}
}
}
.ticket-estimation {
- @extend %estimation;
+ @include estimation;
}
diff --git a/app/styles/components/summary.scss b/app/styles/components/summary.scss
index cd25dc2f..3c25c075 100644
--- a/app/styles/components/summary.scss
+++ b/app/styles/components/summary.scss
@@ -63,6 +63,8 @@ $summary-background: $grayer;
svg {
fill: $black;
height: 100%;
+ max-height: 2rem;
+ max-width: 2rem;
transition: all .2s;
width: 100%;
}
diff --git a/app/styles/components/tag.scss b/app/styles/components/tag.scss
index 7cf06594..d1fcff0b 100644
--- a/app/styles/components/tag.scss
+++ b/app/styles/components/tag.scss
@@ -38,8 +38,9 @@
display: inline-block;
}
input {
+ margin-right: .25rem;
padding: .4rem;
- width: 14rem;
+ width: 10rem;
}
.tag {
@extend %small;
diff --git a/app/styles/components/user-list.scss b/app/styles/components/user-list.scss
index 6247ddff..299014ae 100644
--- a/app/styles/components/user-list.scss
+++ b/app/styles/components/user-list.scss
@@ -1,11 +1,11 @@
-%user-list {
+@mixin user-list {
.user-list-single {
align-content: center;
align-items: center;
background: transparent;
border-bottom: 1px solid $whitish;
display: flex;
- padding: .5rem .5rem .3rem;
+ padding: .25rem 0;
vertical-align: middle;
&:last-child {
@@ -28,7 +28,7 @@
}
.assigned-to-list {
- @extend %user-list;
+ @include user-list;
margin-top: 1rem;
.user-list-single {
&:hover,
@@ -59,7 +59,7 @@
}
.ticket-watchers {
- @extend %user-list;
+ @include user-list;
margin-top: 1rem;
.user-list-single {
&:hover {
diff --git a/app/styles/core/elements.scss b/app/styles/core/elements.scss
index 973d8346..c7d57631 100644
--- a/app/styles/core/elements.scss
+++ b/app/styles/core/elements.scss
@@ -47,6 +47,11 @@ sup {
cursor: move;
}
+svg {
+ max-height: 1rem;
+ max-width: 1rem;
+}
+
//Datepicker
.pika-single {
// scss-lint:disable ImportantRule
diff --git a/app/styles/dependencies/mixins.scss b/app/styles/dependencies/mixins.scss
index a77f687e..2eb9425e 100644
--- a/app/styles/dependencies/mixins.scss
+++ b/app/styles/dependencies/mixins.scss
@@ -133,8 +133,8 @@
}
.icon {
svg {
- max-height: 1rem;
- max-width: 1rem;
+ height: 1rem;
+ width: 1rem;
}
path {
fill: currentcolor;
diff --git a/app/styles/layout/auth.scss b/app/styles/layout/auth.scss
index 393e1eb6..468ba9f2 100644
--- a/app/styles/layout/auth.scss
+++ b/app/styles/layout/auth.scss
@@ -18,6 +18,10 @@
padding: 0 33%;
text-align: center;
width: 100%;
+ svg {
+ max-height: 100%;
+ max-width: 100%;
+ }
}
.logo {
@extend %xxlarge;
diff --git a/app/styles/layout/ticket-detail.scss b/app/styles/layout/ticket-detail.scss
index fcd90e4d..061a81f5 100644
--- a/app/styles/layout/ticket-detail.scss
+++ b/app/styles/layout/ticket-detail.scss
@@ -1,5 +1,5 @@
.us-story-main-data {
- margin-bottom: 2rem;
+ margin-bottom: 1rem;
header {
align-content: center;
align-items: stretch;
@@ -165,6 +165,30 @@
}
}
+.subheader {
+ display: flex;
+ justify-content: space-between;
+ @include breakpoint(laptop) {
+ flex-direction: column;
+ justify-content: flex-start;
+ }
+ .ticket-created-by {
+ flex: 1;
+ flex-basis: 250px;
+ @include breakpoint(laptop) {
+ flex: 0;
+ order: 1;
+ }
+ }
+ .tags-block {
+ flex: 3;
+ @include breakpoint(laptop) {
+ flex: 0;
+ order: 2;
+ }
+ }
+}
+
.duty-content {
@include cursor-progress;
position: relative;
diff --git a/app/styles/modules/backlog/sprints.scss b/app/styles/modules/backlog/sprints.scss
index 40e4a071..7ba4d2cb 100644
--- a/app/styles/modules/backlog/sprints.scss
+++ b/app/styles/modules/backlog/sprints.scss
@@ -17,6 +17,8 @@
}
svg {
height: 1.4rem;
+ max-height: 1.4rem;
+ max-width: 1.5rem;
width: 1.5rem;
}
path {
diff --git a/app/styles/modules/common/assigned-to.scss b/app/styles/modules/common/assigned-to.scss
index 207ae322..15e7d2b9 100644
--- a/app/styles/modules/common/assigned-to.scss
+++ b/app/styles/modules/common/assigned-to.scss
@@ -1,7 +1,10 @@
.ticket-assigned-to {
align-items: center;
+ border-bottom: 1px solid $gray-light;
+ border-top: 1px solid $gray-light;
display: flex;
margin-bottom: 1rem;
+ padding: 1rem 0;
position: relative;
&:hover {
.assigned-to {
@@ -18,11 +21,31 @@
max-width: 2rem;
}
.user-avatar {
- flex-basis: 4rem;
+ flex-basis: 3rem;
flex-shrink: 0;
+ position: relative;
img {
width: 100%;
}
+ &.is-iocaine {
+ img {
+ filter: hue-rotate(150deg) saturate(200%);
+ }
+ }
+ .iocaine-symbol {
+ left: -.5rem;
+ position: absolute;
+ top: -.75rem;
+ z-index: 9;
+ svg {
+ background: $grayer;
+ border-radius: .25rem;
+ fill: $white;
+ min-height: 1.75rem;
+ min-width: 1.75rem;
+ padding: .25rem;
+ }
+ }
}
.assigned-to {
flex-grow: 1;
@@ -32,12 +55,12 @@
@extend %light;
color: $gray;
display: block;
+ margin: .2rem 0 .25rem;
}
.user-assigned {
@extend %large;
color: $primary;
cursor: default;
- line-height: 1.5rem;
&.editable {
cursor: pointer;
}
@@ -54,7 +77,7 @@
opacity: 0;
position: absolute;
right: 0;
- top: 0;
+ top: 2rem;
&:hover {
color: $red;
}
diff --git a/app/styles/modules/common/lightbox.scss b/app/styles/modules/common/lightbox.scss
index 936bbb68..ee9635ed 100644
--- a/app/styles/modules/common/lightbox.scss
+++ b/app/styles/modules/common/lightbox.scss
@@ -507,18 +507,23 @@
}
.lb-create-edit-userstory {
+ .points-per-role {
+ flex-direction: row;
+ flex-wrap: wrap;
+ margin: 0;
+ }
.ticket-role-points {
- flex-grow: 1;
- flex-shrink: 1;
- max-width: calc(100% * (1/6) - .2rem);
+ margin: .1rem;
+ min-width: 20%;
&:first-child {
margin-left: 0;
}
- &:nth-child(5n+5) {
+ &:nth-child(4n + 4) {
margin-right: 0;
}
- }
- .points-per-role {
- margin-bottom: 0;
+ &:last-child {
+ margin: .1rem 0;
+ min-width: 100%;
+ }
}
}
diff --git a/app/styles/modules/common/nav.scss b/app/styles/modules/common/nav.scss
index 6dca70cf..1227a2b2 100644
--- a/app/styles/modules/common/nav.scss
+++ b/app/styles/modules/common/nav.scss
@@ -49,8 +49,12 @@ tg-project-menu {
}
}
}
- svg path {
- opacity: 1;
+ svg {
+ max-height: 1.5rem;
+ max-width: 1.5rem;
+ path {
+ opacity: 1;
+ }
}
span {
display: block;
diff --git a/app/styles/modules/common/ticket-data.scss b/app/styles/modules/common/ticket-data.scss
index a727f403..80dbe413 100644
--- a/app/styles/modules/common/ticket-data.scss
+++ b/app/styles/modules/common/ticket-data.scss
@@ -1,24 +1,54 @@
-.ticket-data {
+.ticket-header {
+ margin: 1.5rem 0 2rem;
.ticket-title {
@extend %larger;
@extend %light;
- margin: 1.5rem 0 2rem;
text-transform: uppercase;
- span {
- margin-right: .25rem;
- &:last-child {
- @extend %large;
- }
- }
+ vertical-align: sub;
}
- .ticket-data-container {
+ .detail-status {
@extend %small;
- @extend %normal;
- margin-bottom: 1rem;
- .icon {
+ display: inline-block;
+ margin-left: .25rem;
+ position: relative;
+ .icon-arrow-bottom {
margin-left: .25rem;
}
}
+ .detail-status-inner {
+ color: $white;
+ display: flex;
+ justify-content: center;
+ padding: .15rem .25rem;
+ text-transform: uppercase;
+ }
+ .pop-status {
+ @include popover(150px, 1.25rem, 0, '', '');
+ padding: 0;
+ text-transform: none;
+ a {
+ @extend %text;
+ padding: .5rem 1rem;
+ }
+ a:hover {
+ background: rgba($primary-light, .2);
+ }
+ }
+}
+
+.ticket-data-container {
+ @extend %small;
+ @extend %normal;
+ margin-bottom: 1rem;
+ .icon {
+ margin-left: .25rem;
+ }
+}
+
+.ticket-status {
+ &:last-child {
+ margin: 0;
+ }
.level {
display: inline-block;
margin-right: .5rem;
@@ -29,29 +59,6 @@
float: right;
text-transform: lowercase;
}
-
- .ticket-estimation {
- .ticket-role-points {
- max-width: 25%;
- &:first-child {
- flex-basis: 100%;
- max-width: 100%;
- }
- }
- }
-}
-
-.ticket-status {
- margin-bottom: .5rem;
- &:last-child {
- margin: 0;
- }
- div {
- background: darken($whitish, 5%);
- padding: .5rem;
- padding-right: 1rem;
- transition: background .2s ease-in;
- }
.clickable {
&:hover {
background: darken($whitish, 10%);
@@ -59,142 +66,153 @@
}
}
.type-data {
+ background: darken($whitish, 5%);
+ margin-bottom: .5rem;
+ padding: .5rem;
+ padding-right: 1rem;
position: relative;
+ transition: background .2s ease-in;
.pop-type {
@include popover(150px, '', 30px, '', '');
}
}
.severity-data {
+ background: darken($whitish, 5%);
+ margin-bottom: .5rem;
+ padding: .5rem;
+ padding-right: 1rem;
position: relative;
+ transition: background .2s ease-in;
.pop-severity {
@include popover(150px, '', 30px, '', '');
}
}
.priority-data {
+ background: darken($whitish, 5%);
+ margin-bottom: .5rem;
+ padding: .5rem;
+ padding-right: 1rem;
position: relative;
+ transition: background .2s ease-in;
.pop-priority {
@include popover(150px, '', 30px, '', '');
}
}
- .status-data {
- position: relative;
- .pop-status {
- @include popover(150px, '', 30px, '', '');
- }
- }
}
-.ticket-track-buttons {
- .track-inner {
+.ticket-watch {
+ .ticket-watch-title {
+ @extend %bold;
+ margin-bottom: .5rem;
+ }
+ .ticket-watch-inner {
+ display: flex;
+ }
+ .track-icon {
+ position: relative;
+ top: 2px;
+ }
+ .ticket-watch-button,
+ .add-watcher {
@extend %light;
@extend %small;
- background: darken($whitish, 5%);
+ background: $gray-light;
+ color: $white;
+ flex: 1;
padding: .25rem;
+ text-align: center;
text-transform: uppercase;
transition: background .25s;
- &:hover {
- background: darken($whitish, 10%);
- }
- }
- .track-button {
- width: 100%;
- }
- .active {
- .track-button-counter {
- background: rgba($grayer, .5);
+ path {
+ fill: $white;
}
&:hover {
- .track-inner {
- background: rgba($primary-light, .2);
- }
+ background: $primary-light;
}
&.is-hover {
- .track-inner {
- background: $red;
- color: $whitish;
- transition: background .3s;
- }
- path {
+ background: $red;
+ color: $whitish;
+ transition: background .3s;
+ svg {
fill: $red-light;
}
}
- }
- .track-button-counter {
- @extend %large;
- background: rgba($grayer, .25);
- color: $whitish;
- padding: 0 .5rem;
- }
- .vote-button {
- margin-bottom: .3rem;
- }
- .watch-button {
- border-bottom: 0;
- }
- .ticket-watchers {
- margin: .5rem 0;
- }
- .add-watcher {
- display: block;
- margin: .5rem;
- .icon {
- background: rgba($grayer, .25);
- color: $whitish;
- margin-right: .5rem;
- padding: .25rem;
- }
- &:hover {
- .icon {
- background: $primary-light;
- color: $whitish;
- transition: background .3s linear;
+ &.active {
+ background: $primary-light;
+ &:hover {
+ background: $red-light;
+ }
+ svg {
+ fill: $white;
}
}
+
+ }
+ .ticket-watch-button {
+ margin-right: .25rem;
}
}
.ticket-detail-settings {
+ display: flex;
+ justify-content: center;
margin-top: 2rem;
label,
- .button {
- display: block;
- margin-bottom: .5rem;
- text-align: center;
- &.editable {
+ .item-block,
+ .item-unblock,
+ .promote-button,
+ .button-delete {
+ background: $gray-light;
+ display: inline-block;
+ margin-right: .5rem;
+ padding: 1rem;
+ transition: background .2s linear;
+ transition-delay: .1s;
+ &:hover {
+ background: $gray-light;
+ cursor: default;
+ }
+ &.is-editable {
+ background: $gray-light;
cursor: pointer;
+ &:hover {
+ background: $gray;
+ }
+ }
+ &.active {
+ background: $primary-light;
}
+input {
display: none;
}
}
- .loading-spinner {
- @extend %loading-spinner;
+ .item-block,
+ .item-unblock {
+ display: none;
+ &.is-active {
+ display: inline-block;
+ }
}
- .button-gray {
- background: $gray-light;
+ .item-unblock {
+ background: $red;
+ }
+ .button-delete {
+ background: $red-light;
&:hover {
- background: $gray-light;
- }
- &.editable {
- &:hover {
- background: $grayer;
- cursor: pointer;
- }
- }
- &.active {
- background: $primary;
+ background: $red;
+ cursor: pointer;
}
}
- .item-block {
- &.editable {
- &:hover {
- background: $red;
- cursor: pointer;
- }
- }
+ img {
+ max-height: 1.25rem;
+ max-width: 1.25rem;
+ width: 100%;
}
- .button-red {
- display: block;
- margin-top: 2rem;
+ svg {
+ fill: $white;
+ height: 100%;
+ max-height: 1.25rem;
+ max-width: 1.25rem;
+ width: 100%;
}
}
diff --git a/app/svg/client-requirement.svg b/app/svg/client-requirement.svg
new file mode 100644
index 00000000..fd20989a
--- /dev/null
+++ b/app/svg/client-requirement.svg
@@ -0,0 +1,4 @@
+
diff --git a/app/svg/iocaine.svg b/app/svg/iocaine.svg
new file mode 100644
index 00000000..868c76d0
--- /dev/null
+++ b/app/svg/iocaine.svg
@@ -0,0 +1,4 @@
+
diff --git a/app/svg/lock.svg b/app/svg/lock.svg
index b2ee1e5a..d39b2ba0 100644
--- a/app/svg/lock.svg
+++ b/app/svg/lock.svg
@@ -1,7 +1,3 @@
-
-
-