Convert tg-tag-line in two directives
parent
5952ab306b
commit
5a73910a89
|
@ -93,89 +93,274 @@ ColorizeTagsDirective = ->
|
|||
|
||||
module.directive("tgColorizeTags", ColorizeTagsDirective)
|
||||
|
||||
|
||||
#############################################################################
|
||||
## TagLine (possible should be moved as generic directive)
|
||||
## TagLine Directive (for Lightboxes)
|
||||
#############################################################################
|
||||
|
||||
TagLineDirective = ($rootscope, $log, $rs, $tgrepo, $confirm) ->
|
||||
# Main directive template (rendered by angular)
|
||||
LbTagLineDirective = ($rs) ->
|
||||
ENTER_KEY = 13
|
||||
|
||||
template = """
|
||||
<div class="tags-container"></div>
|
||||
<a href="#" class="add-tag" title="Add tag">
|
||||
<span class="icon icon-plus"></span>
|
||||
<span class="add-tag-text">Add tag</span>
|
||||
</a>
|
||||
<input type="text" placeholder="Write tag..." class="tag-input" />
|
||||
<a href="" title="Save" class="save icon icon-floppy"></a>
|
||||
"""
|
||||
<a href="" title="Save" class="save icon icon-floppy hidden"></a>
|
||||
""" # TODO: i18n
|
||||
|
||||
# Tags template (rendered manually using lodash)
|
||||
templateTags = _.template("""
|
||||
<% _.each(tags, function(tag) { %>
|
||||
<span class="tag" style="border-left: 5px solid <%- tag.color %>;">
|
||||
<span class="tag-name"><%- tag.name %></span>
|
||||
<% if (editable) { %>
|
||||
<a href="" title="delete tag" class="icon icon-delete"></a>
|
||||
<% } %>
|
||||
</span>
|
||||
<% }); %>""")
|
||||
<% }); %>
|
||||
""") # TODO: i18n
|
||||
|
||||
link = ($scope, $el, $attrs, $model) ->
|
||||
editable = false
|
||||
|
||||
$el.addClass("tags-block")
|
||||
$el.find("input").hide()
|
||||
|
||||
renderTags = ($el, tags, editable, tagsColors) ->
|
||||
renderTags = (tags, tagsColors) ->
|
||||
ctx = {
|
||||
tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]})
|
||||
editable: editable
|
||||
}
|
||||
html = templateTags(ctx)
|
||||
$el.find("div.tags-container").html(html)
|
||||
|
||||
normalizeTags = (tags) ->
|
||||
tags = _.map(tags, trim)
|
||||
tags = _.map(tags, (x) -> x.toLowerCase())
|
||||
return _.uniq(tags)
|
||||
showSaveButton = -> $el.find(".save").removeClass("hidden")
|
||||
hideSaveButton = -> $el.find(".save").addClass("hidden")
|
||||
|
||||
resetInput = ->
|
||||
$el.find("input").val("")
|
||||
$el.find("input").autocomplete("close")
|
||||
|
||||
addValue = (value) ->
|
||||
value = trim(value)
|
||||
return if value.length <= 0
|
||||
value = trim(value.toLowerCase())
|
||||
return if value.length == 0
|
||||
|
||||
tags = _.clone($model.$modelValue, false)
|
||||
tags = [] if not tags?
|
||||
tags.push(value)
|
||||
tags.push(value) if value not in tags
|
||||
|
||||
$scope.$apply ->
|
||||
$model.$setViewValue(normalizeTags(tags))
|
||||
autosaveModel = $scope.$eval($attrs.autosaveModel)
|
||||
if autosaveModel
|
||||
promise = $tgrepo.save(autosaveModel)
|
||||
promise.then ->
|
||||
$rootscope.$broadcast("history:reload")
|
||||
promise.then null, ->
|
||||
$confirm.notify("error")
|
||||
$model.$setViewValue(tags)
|
||||
|
||||
saveInputTag = () ->
|
||||
input = $el.find('input')
|
||||
value = $el.find("input").val()
|
||||
|
||||
addValue(input.val())
|
||||
input.val("")
|
||||
input.autocomplete("close")
|
||||
$el.find('.save').hide()
|
||||
addValue(value)
|
||||
resetInput()
|
||||
hideSaveButton()
|
||||
|
||||
$el.on "keypress", "input", (event) ->
|
||||
return if event.keyCode != ENTER_KEY
|
||||
event.preventDefault()
|
||||
|
||||
$el.on "keyup", "input", (event) ->
|
||||
target = angular.element(event.currentTarget)
|
||||
|
||||
if event.keyCode == ENTER_KEY
|
||||
saveInputTag()
|
||||
else
|
||||
if target.val().length
|
||||
showSaveButton()
|
||||
else
|
||||
hideSaveButton()
|
||||
|
||||
$el.on "click", ".save", (event) ->
|
||||
event.preventDefault()
|
||||
saveInputTag
|
||||
|
||||
$el.on "click", ".icon-delete", (event) ->
|
||||
event.preventDefault()
|
||||
target = angular.element(event.currentTarget)
|
||||
|
||||
value = target.siblings(".tag-name").text()
|
||||
tags = _.clone($model.$modelValue, false)
|
||||
tags = _.pull(tags, value)
|
||||
|
||||
$scope.$apply ->
|
||||
$model.$setViewValue(tags)
|
||||
|
||||
bindOnce $scope, "project", (project) ->
|
||||
# If not editable, no tags preloading is needed.
|
||||
editable = project.my_permissions.indexOf($attrs.requiredPerm) != -1
|
||||
positioningFunction = (position, elements) ->
|
||||
menu = elements.element.element
|
||||
menu.css("width", elements.target.width)
|
||||
menu.css("top", position.top)
|
||||
menu.css("left", position.left)
|
||||
|
||||
if not $scope.$eval($attrs.autosaveModel)?
|
||||
$el.find("a.save").remove()
|
||||
$rs.projects.tags(project.id).then (data) ->
|
||||
$el.find("input").autocomplete({
|
||||
source: data
|
||||
position: {
|
||||
my: "left top",
|
||||
using: positioningFunction
|
||||
}
|
||||
select: (event, ui) ->
|
||||
addValue(ui.item.value)
|
||||
ui.item.value = ""
|
||||
})
|
||||
|
||||
if not editable
|
||||
$el.find("input").remove()
|
||||
$scope.$watch $attrs.ngModel, (tags) ->
|
||||
tagsColors = $scope.project?.tags_colors or []
|
||||
renderTags(tags, tagsColors)
|
||||
|
||||
$scope.$on "$destroy", ->
|
||||
$el.off()
|
||||
|
||||
return {
|
||||
link:link,
|
||||
require:"ngModel"
|
||||
template: template
|
||||
}
|
||||
|
||||
module.directive("tgLbTagLine", ["$tgResources", LbTagLineDirective])
|
||||
|
||||
|
||||
#############################################################################
|
||||
## TagLine Directive (for detail pages)
|
||||
#############################################################################
|
||||
|
||||
TagLineDirective = ($rootScope, $repo, $rs, $confirm) ->
|
||||
ENTER_KEY = 13
|
||||
ESC_KEY = 27
|
||||
|
||||
template = """
|
||||
<div class="tags-container"></div>
|
||||
<a href="#" class="add-tag hidden" title="Add tag">
|
||||
<span class="icon icon-plus"></span>
|
||||
<span class="add-tag-text">Add tag</span>
|
||||
</a>
|
||||
<input type="text" placeholder="Write tag..." class="tag-input hidden" />
|
||||
<a href="" title="Save" class="save icon icon-floppy hidden"></a>
|
||||
""" # TODO: i18n
|
||||
|
||||
# Tags template (rendered manually using lodash)
|
||||
templateTags = _.template("""
|
||||
<% _.each(tags, function(tag) { %>
|
||||
<span class="tag" style="border-left: 5px solid <%- tag.color %>;">
|
||||
<span class="tag-name"><%- tag.name %></span>
|
||||
<% if (isEditable) { %>
|
||||
<a href="" title="delete tag" class="icon icon-delete"></a>
|
||||
<% } %>
|
||||
</span>
|
||||
<% }); %>
|
||||
""") # TODO: i18n
|
||||
|
||||
link = ($scope, $el, $attrs, $model) ->
|
||||
isEditable = ->
|
||||
return $scope.project.my_permissions.indexOf($attrs.requiredPerm) != -1
|
||||
|
||||
renderTags = (tags, tagsColors) ->
|
||||
ctx = {
|
||||
tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]})
|
||||
isEditable: isEditable()
|
||||
}
|
||||
html = templateTags(ctx)
|
||||
$el.find("div.tags-container").html(html)
|
||||
|
||||
renderInReadModeOnly = ->
|
||||
$el.find(".add-tag").remove()
|
||||
$el.find("input").remove()
|
||||
$el.find(".save").remove()
|
||||
|
||||
showAddTagButton = -> $el.find(".add-tag").removeClass("hidden")
|
||||
hideAddTagButton = -> $el.find(".add-tag").addClass("hidden")
|
||||
|
||||
showAddTagButtonText = -> $el.find(".add-tag-text").removeClass("hidden")
|
||||
hideAddTagButtonText = -> $el.find(".add-tag-text").addClass("hidden")
|
||||
|
||||
showSaveButton = -> $el.find(".save").removeClass("hidden")
|
||||
hideSaveButton = -> $el.find(".save").addClass("hidden")
|
||||
|
||||
showInput = -> $el.find("input").removeClass("hidden")
|
||||
hideInput = -> $el.find("input").addClass("hidden")
|
||||
resetInput = ->
|
||||
$el.find("input").val("")
|
||||
$el.find("input").autocomplete("close")
|
||||
|
||||
addValue = (value) ->
|
||||
value = trim(value.toLowerCase())
|
||||
return if value.length == 0
|
||||
|
||||
tags = _.clone($model.$modelValue, false)
|
||||
tags = [] if not tags?
|
||||
tags.push(value) if value not in tags
|
||||
|
||||
$scope.$apply ->
|
||||
$model.$setViewValue(tags)
|
||||
|
||||
autosaveModel = $scope.$eval($attrs.autosaveModel)
|
||||
if autosaveModel
|
||||
onSuccess = ->
|
||||
$rootScope.$broadcast("history:reload")
|
||||
onError = ->
|
||||
$confirm.notify("error")
|
||||
$scope.$apply ->
|
||||
autosaveModel.revert()
|
||||
$repo.save(autosaveModel).then(onSuccess, onError)
|
||||
|
||||
saveInputTag = () ->
|
||||
value = $el.find("input").val()
|
||||
|
||||
addValue(value)
|
||||
resetInput()
|
||||
hideSaveButton()
|
||||
|
||||
$el.on "keypress", "input", (event) ->
|
||||
return if event.keyCode not in [ENTER_KEY, ESC_KEY]
|
||||
event.preventDefault()
|
||||
|
||||
$el.on "keyup", "input", (event) ->
|
||||
target = angular.element(event.currentTarget)
|
||||
|
||||
if event.keyCode == ENTER_KEY
|
||||
saveInputTag()
|
||||
else if event.keyCode == ESC_KEY
|
||||
resetInput()
|
||||
hideInput()
|
||||
hideSaveButton()
|
||||
showAddTagButton()
|
||||
else
|
||||
if target.val().length
|
||||
showSaveButton()
|
||||
else
|
||||
hideSaveButton()
|
||||
|
||||
$el.on "click", ".save", (event) ->
|
||||
event.preventDefault()
|
||||
saveInputTag()
|
||||
|
||||
$el.on "click", ".add-tag", (event) ->
|
||||
event.preventDefault()
|
||||
hideAddTagButton()
|
||||
showInput()
|
||||
|
||||
$el.on "click", ".icon-delete", (event) ->
|
||||
event.preventDefault()
|
||||
target = angular.element(event.currentTarget)
|
||||
|
||||
value = target.siblings(".tag-name").text()
|
||||
tags = _.clone($model.$modelValue, false)
|
||||
tags = _.pull(tags, value)
|
||||
|
||||
$scope.$apply ->
|
||||
$model.$setViewValue(tags)
|
||||
|
||||
autosaveModel = $scope.$eval($attrs.autosaveModel)
|
||||
if autosaveModel
|
||||
onSuccess = ->
|
||||
$rootScope.$broadcast("history:reload")
|
||||
onError = ->
|
||||
$confirm.notify("error")
|
||||
$scope.$apply ->
|
||||
autosaveModel.revert()
|
||||
$repo.save(autosaveModel).then(onSuccess, onError)
|
||||
|
||||
bindOnce $scope, "project", (project) ->
|
||||
if not isEditable()
|
||||
renderInReadModeOnly()
|
||||
return
|
||||
|
||||
showAddTagButton()
|
||||
|
||||
positioningFunction = (position, elements) ->
|
||||
menu = elements.element.element
|
||||
|
@ -195,62 +380,17 @@ TagLineDirective = ($rootscope, $log, $rs, $tgrepo, $confirm) ->
|
|||
ui.item.value = ""
|
||||
})
|
||||
|
||||
$el.on "keypress", "input", (event) ->
|
||||
return if event.keyCode not in [13, 27]
|
||||
event.preventDefault()
|
||||
$scope.$watch $attrs.ngModel, (tags) ->
|
||||
return if not tags
|
||||
|
||||
$el.on "keyup", "input", (event) ->
|
||||
target = angular.element(event.currentTarget)
|
||||
|
||||
if event.keyCode == 13
|
||||
saveInputTag()
|
||||
else if event.keyCode == 27
|
||||
$el.find('.save').hide()
|
||||
$el.find("input").hide()
|
||||
$el.find("input").val('')
|
||||
$el.find('.add-tag').show()
|
||||
else if target.val().length
|
||||
$el.find('.save').show()
|
||||
if tags.length
|
||||
hideAddTagButtonText()
|
||||
else
|
||||
$el.find('.save').hide()
|
||||
showAddTagButtonText()
|
||||
|
||||
$el.on "click", ".save", saveInputTag
|
||||
tagsColors = $scope.project?.tags_colors or []
|
||||
renderTags(tags, tagsColors)
|
||||
|
||||
$el.on "click", ".add-tag", (event) ->
|
||||
event.preventDefault()
|
||||
target = angular.element(event.currentTarget)
|
||||
target.hide()
|
||||
target.siblings('input').show()
|
||||
|
||||
$el.on "click", ".icon-delete", (event) ->
|
||||
event.preventDefault()
|
||||
target = angular.element(event.currentTarget)
|
||||
value = trim(target.siblings(".tag-name").text())
|
||||
|
||||
if value.length <= 0
|
||||
return
|
||||
|
||||
tags = _.clone($model.$modelValue, false)
|
||||
tags = _.pull(tags, value)
|
||||
|
||||
$scope.$apply ->
|
||||
$model.$setViewValue(normalizeTags(tags))
|
||||
autosaveModel = $scope.$eval($attrs.autosaveModel)
|
||||
if autosaveModel
|
||||
promise = $tgrepo.save(autosaveModel)
|
||||
promise.then ->
|
||||
$rootscope.$broadcast("history:reload")
|
||||
promise.then null, ->
|
||||
$confirm.notify("error")
|
||||
|
||||
$scope.$watch $attrs.ngModel, (val) ->
|
||||
tags_colors = if $scope.project?.tags_colors? then $scope.project.tags_colors else []
|
||||
renderTags($el, val, editable, tags_colors)
|
||||
|
||||
if val? and val.length > 0
|
||||
$el.find("span.add-tag-text").hide()
|
||||
else
|
||||
$el.find("span.add-tag-text").show()
|
||||
|
||||
$scope.$on "$destroy", ->
|
||||
$el.off()
|
||||
|
@ -261,4 +401,4 @@ TagLineDirective = ($rootscope, $log, $rs, $tgrepo, $confirm) ->
|
|||
template: template
|
||||
}
|
||||
|
||||
module.directive("tgTagLine", ["$rootScope", "$log", "$tgResources", "$tgRepo", "$tgConfirm", TagLineDirective])
|
||||
module.directive("tgTagLine", ["$rootScope", "$tgRepo", "$tgResources", "$tgConfirm", TagLineDirective])
|
||||
|
|
|
@ -14,7 +14,7 @@ form
|
|||
select.severity(ng-model="issue.severity", ng-options="s.id as s.name for s in severityList")
|
||||
|
||||
fieldset
|
||||
div(tg-tag-line, ng-model="issue.tags", required-perm="add_issue")
|
||||
div.tags-block(tg-lb-tag-line, ng-model="issue.tags")
|
||||
|
||||
fieldset
|
||||
textarea.description(placeholder="Description", ng-model="issue.description")
|
||||
|
|
|
@ -15,9 +15,8 @@ form
|
|||
placeholder="Assigned to")
|
||||
option(value="") Unassigned
|
||||
|
||||
fieldset(ng-switch="isNew")
|
||||
div(ng-switch-when="true", tg-tag-line, ng-model="task.tags", required-perm="add_task")
|
||||
div(ng-switch-default, tg-tag-line, ng-model="task.tags", required-perm="modify_task")
|
||||
fieldset
|
||||
div.tags-block(tg-lb-tag-line, ng-model="task.tags")
|
||||
|
||||
fieldset
|
||||
textarea.description(placeholder="Type a short description", ng-model="task.description")
|
||||
|
|
|
@ -13,9 +13,8 @@ form
|
|||
select(name="status", ng-model="us.status", ng-options="s.id as s.name for s in usStatusList",
|
||||
tr="placeholder:common.status")
|
||||
|
||||
fieldset(ng-switch="isNew")
|
||||
div(ng-switch-when="true", tg-tag-line, ng-model="us.tags", required-perm="add_us")
|
||||
div(ng-switch-default, tg-tag-line, ng-model="us.tags", required-perm="modify_us")
|
||||
fieldset
|
||||
div.tags-block(tg-lb-tag-line, ng-model="us.tags")
|
||||
|
||||
fieldset
|
||||
textarea.description(name="description", ng-model="us.description",
|
||||
|
|
|
@ -54,9 +54,6 @@
|
|||
.add-tag-text {
|
||||
@extend %small;
|
||||
}
|
||||
.save {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue