Files
gitlabhq/app/assets/javascripts/awards_handler.coffee
T
Fatih Acet 85e9eece7e Fix displaying emoji only comments.
To render emoji in the emoji bar of an issue or MR we actually need the emoji unicode and unicode info is stored in the emoji menu widget. That widget could only be visible if user clicks the "Add" button and there may not be a widget when posting emoji only comments. So this change will check existence of the widget and create it before posting the emoji if it's not exist to render it correctly.
2016-05-23 21:33:58 +03:00

279 lines
8.2 KiB
CoffeeScript

class @AwardsHandler
constructor: ->
@aliases = emojiAliases()
$(document)
.off "click", ".js-add-award"
.on "click", ".js-add-award", (event) =>
event.stopPropagation()
event.preventDefault()
@showEmojiMenu $(event.currentTarget)
$("html").on 'click', (event) ->
if !$(event.target).closest(".emoji-menu").length
if $(".emoji-menu").is(":visible")
$('.js-add-award.is-active').removeClass 'is-active'
$(".emoji-menu").removeClass "is-visible"
$(document)
.off "click", ".js-emoji-btn"
.on "click", ".js-emoji-btn", @handleClick
handleClick: (e) =>
e.preventDefault()
$emojiBtn = $(e.currentTarget)
$addAwardBtn = $('.js-add-award.is-active')
$votesBlock = $($addAwardBtn.closest('.js-award-holder').data('target'))
if $addAwardBtn.length is 0
$votesBlock = $emojiBtn.closest('.js-awards-block')
else if $votesBlock.length is 0
$votesBlock = $addAwardBtn.closest('.js-awards-block')
$votesBlock.addClass 'js-awards-block'
awardUrl = $votesBlock.data 'award-url'
emoji = $emojiBtn.find('.icon').data('emoji')
@addAward awardUrl, emoji
showEmojiMenu: ($addBtn) ->
$menu = $('.emoji-menu')
if $menu.length
$holder = $addBtn.closest('.js-award-holder')
if $menu.is ".is-visible"
$addBtn.removeClass "is-active"
$menu.removeClass "is-visible"
$("#emoji_search").blur()
else
$addBtn.addClass "is-active"
@positionMenu($menu, $addBtn)
$menu.addClass "is-visible"
$("#emoji_search").focus()
else
$addBtn.addClass 'is-loading is-active'
url = $addBtn.data 'award-menu-url'
@createEmojiMenu url, =>
$addBtn.removeClass 'is-loading'
$menu = $('.emoji-menu')
@positionMenu($menu, $addBtn)
@renderFrequentlyUsedBlock()
setTimeout =>
$menu.addClass 'is-visible'
$('#emoji_search').focus()
@setupSearch()
, 200
createEmojiMenu: (awardMenuUrl, callback) ->
$.get awardMenuUrl, (response) =>
$('body').append response
callback()
positionMenu: ($menu, $addBtn) ->
position = $addBtn.data('position')
# The menu could potentially be off-screen or in a hidden overflow element
# So we position the element absolute in the body
css =
top: "#{$addBtn.offset().top + $addBtn.outerHeight()}px"
if position? and position is 'right'
css.left = "#{($addBtn.offset().left - $menu.outerWidth()) + 20}px"
$menu.addClass "is-aligned-right"
else
css.left = "#{$addBtn.offset().left}px"
$menu.removeClass "is-aligned-right"
$menu.css(css)
addAward: (awardUrl, emoji) ->
emoji = @normilizeEmojiName(emoji)
@postEmoji awardUrl, emoji, =>
@addAwardToEmojiBar(emoji)
$('.js-awards-block-current').removeClass 'js-awards-block-current'
$(".emoji-menu").removeClass "is-visible"
addAwardToEmojiBar: (emoji) ->
@addEmojiToFrequentlyUsedList(emoji)
emoji = @normilizeEmojiName(emoji)
$emojiBtn = @findEmojiIcon(emoji).parent()
if $emojiBtn.length > 0
if @isActive($emojiBtn)
@decrementCounter($emojiBtn, emoji)
else
counter = $emojiBtn.find('.js-counter')
counter.text(parseInt(counter.text()) + 1)
$emojiBtn.addClass("active")
@addMeToUserList(emoji)
else
@createEmoji(emoji)
isActive: ($emojiBtn) ->
$emojiBtn.hasClass("active")
decrementCounter: ($emojiBtn, emoji) ->
isntNoteBody = $emojiBtn.closest('.note-body').length is 0
counter = $('.js-counter', $emojiBtn)
counterNumber = parseInt(counter.text())
if !isntNoteBody
# If this is a note body, we just hide the award emoji row like the initial state
$emojiBtn.closest('.js-awards-block').addClass 'hidden'
if counterNumber > 1
counter.text(counterNumber - 1)
@removeMeFromUserList($emojiBtn, emoji)
else if (emoji == "thumbsup" || emoji == "thumbsdown") && isntNoteBody
$emojiBtn.tooltip("destroy")
counter.text('0')
@removeMeFromUserList($emojiBtn, emoji)
else
$emojiBtn.tooltip("destroy")
$emojiBtn.remove()
$emojiBtn.removeClass("active")
removeMeFromUserList: ($emojiBtn, emoji) ->
award_block = $emojiBtn
authors = award_block
.attr("data-original-title")
.split(", ")
authors.splice(authors.indexOf("me"),1)
award_block
.closest(".js-emoji-btn")
.attr("data-original-title", authors.join(", "))
@resetTooltip(award_block)
addMeToUserList: (emoji) ->
award_block = @findEmojiIcon(emoji).parent()
origTitle = award_block.attr("data-original-title").trim()
users = []
if origTitle
users = origTitle.split(', ')
users.push("me")
award_block.attr("title", users.join(", "))
@resetTooltip(award_block)
resetTooltip: (award) ->
award.tooltip("destroy")
# "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
setTimeout (->
award.tooltip()
), 200
createEmoji_: (emoji) ->
emojiCssClass = @resolveNameToCssClass emoji
buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='me' data-placement='bottom'>
<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>
<span class='award-control-text js-counter'>1</span>
</button>"
emoji_node = $(buttonHtml)
.insertBefore '.js-awards-block .js-award-holder:not(.js-award-action-btn)'
.find '.emoji-icon'
.data 'emoji', emoji
$('.award-control').tooltip()
$currentBlock = $ '.js-awards-block'
if $currentBlock.is '.hidden'
$currentBlock.removeClass 'hidden'
createEmoji: (emoji) ->
return @createEmoji_ emoji if $('.emoji-menu').length
awardMenuUrl = $('[data-award-menu-url]').data 'award-menu-url'
@createEmojiMenu awardMenuUrl, => @createEmoji emoji
resolveNameToCssClass: (emoji) ->
emoji_icon = $(".emoji-menu-content [data-emoji='#{emoji}']")
if emoji_icon.length > 0
unicodeName = emoji_icon.data("unicode-name")
else
# Find by alias
unicodeName = $(".emoji-menu-content [data-aliases*=':#{emoji}:']").data("unicode-name")
return "emoji-#{unicodeName}"
postEmoji: (awardUrl, emoji, callback) ->
$.post awardUrl, { name: emoji }, (data) ->
if data.ok
callback.call()
findEmojiIcon: (emoji) ->
$(".js-awards-block.awards > .js-emoji-btn [data-emoji='#{emoji}']")
scrollToAwards: ->
$('body, html').animate({
scrollTop: $('.awards').offset().top - 80
}, 200)
normilizeEmojiName: (emoji) ->
@aliases[emoji] || emoji
addEmojiToFrequentlyUsedList: (emoji) ->
frequently_used_emojis = @getFrequentlyUsedEmojis()
frequently_used_emojis.push(emoji)
$.cookie('frequently_used_emojis', frequently_used_emojis.join(","), { expires: 365 })
getFrequentlyUsedEmojis: ->
frequently_used_emojis = ($.cookie('frequently_used_emojis') || "").split(",")
_.compact(_.uniq(frequently_used_emojis))
renderFrequentlyUsedBlock: ->
if $.cookie('frequently_used_emojis')
frequently_used_emojis = @getFrequentlyUsedEmojis()
ul = $("<ul class='clearfix emoji-menu-list'>")
for emoji in frequently_used_emojis
$(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul)
$("input.emoji-search").after(ul).after($("<h5>").text("Frequently used"))
setupSearch: ->
$("input.emoji-search").on 'keyup', (ev) =>
term = $(ev.target).val()
# Clean previous search results
$("ul.emoji-menu-search, h5.emoji-search").remove()
if term
# Generate a search result block
h5 = $("<h5>").text("Search results").addClass("emoji-search")
found_emojis = @searchEmojis(term).show()
ul = $("<ul>").addClass("emoji-menu-list emoji-menu-search").append(found_emojis)
$(".emoji-menu-content ul, .emoji-menu-content h5").hide()
$(".emoji-menu-content").append(h5).append(ul)
else
$(".emoji-menu-content").children().show()
searchEmojis: (term)->
$(".emoji-menu-content [data-emoji*='#{term}']").closest("li").clone()