Convert tg-tag-line in two directives

stable
David Barragán Merino 2014-10-23 20:16:45 +02:00
parent 5952ab306b
commit 5a73910a89
5 changed files with 243 additions and 108 deletions

View File

@ -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
$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])

View File

@ -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")

View File

@ -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")

View File

@ -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",

View File

@ -54,9 +54,6 @@
.add-tag-text {
@extend %small;
}
.save {
display: none;
}
}