Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Jérome Perrin
gitlab-ce
Commits
1311f8c2
Commit
1311f8c2
authored
Jun 06, 2016
by
Kamil Trzcinski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'rename-ci-commit-phase-2' into rename-ci-commit-phase-3
parents
ef35ca23
4e38d88d
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
1798 additions
and
156 deletions
+1798
-156
CHANGELOG
CHANGELOG
+1
-0
app/assets/javascripts/application.js.coffee
app/assets/javascripts/application.js.coffee
+1
-1
app/assets/javascripts/awards_handler.coffee
app/assets/javascripts/awards_handler.coffee
+163
-109
app/assets/javascripts/dispatcher.js.coffee
app/assets/javascripts/dispatcher.js.coffee
+2
-2
app/assets/javascripts/due_date_select.js.coffee
app/assets/javascripts/due_date_select.js.coffee
+3
-2
app/assets/javascripts/lib/emoji_aliases.js.coffee.erb
app/assets/javascripts/lib/emoji_aliases.js.coffee.erb
+1
-1
app/assets/javascripts/milestone_select.js.coffee
app/assets/javascripts/milestone_select.js.coffee
+2
-2
app/assets/javascripts/notes.js.coffee
app/assets/javascripts/notes.js.coffee
+4
-3
app/assets/javascripts/users_select.js.coffee
app/assets/javascripts/users_select.js.coffee
+1
-1
app/assets/stylesheets/framework/timeline.scss
app/assets/stylesheets/framework/timeline.scss
+1
-1
app/assets/stylesheets/pages/awards.scss
app/assets/stylesheets/pages/awards.scss
+3
-1
app/assets/stylesheets/pages/notes.scss
app/assets/stylesheets/pages/notes.scss
+32
-0
app/controllers/concerns/toggle_award_emoji.rb
app/controllers/concerns/toggle_award_emoji.rb
+10
-1
app/controllers/projects/notes_controller.rb
app/controllers/projects/notes_controller.rb
+3
-0
app/models/note.rb
app/models/note.rb
+1
-0
app/views/award_emoji/_awards_block.html.haml
app/views/award_emoji/_awards_block.html.haml
+1
-1
app/views/projects/issues/show.html.haml
app/views/projects/issues/show.html.haml
+3
-3
app/views/projects/notes/_note.html.haml
app/views/projects/notes/_note.html.haml
+6
-1
config/routes.rb
config/routes.rb
+1
-0
spec/controllers/projects/notes_controller_spec.rb
spec/controllers/projects/notes_controller_spec.rb
+36
-0
spec/features/issues_spec.rb
spec/features/issues_spec.rb
+2
-6
spec/javascripts/awards_handler_spec.js.coffee
spec/javascripts/awards_handler_spec.js.coffee
+202
-0
spec/javascripts/behaviors/quick_submit_spec.js.coffee
spec/javascripts/behaviors/quick_submit_spec.js.coffee
+11
-11
spec/javascripts/fixtures/awards_handler.html.haml
spec/javascripts/fixtures/awards_handler.html.haml
+52
-0
spec/javascripts/fixtures/behaviors/quick_submit.html.haml
spec/javascripts/fixtures/behaviors/quick_submit.html.haml
+1
-1
spec/javascripts/fixtures/emoji_menu.coffee
spec/javascripts/fixtures/emoji_menu.coffee
+957
-0
spec/javascripts/graphs/stat_graph_contributors_util_spec.js
spec/javascripts/graphs/stat_graph_contributors_util_spec.js
+6
-6
spec/javascripts/new_branch_spec.js.coffee
spec/javascripts/new_branch_spec.js.coffee
+1
-1
spec/lib/gitlab/badge/build_spec.rb
spec/lib/gitlab/badge/build_spec.rb
+23
-2
spec/models/note_spec.rb
spec/models/note_spec.rb
+10
-0
vendor/assets/javascripts/task_list.js.coffee
vendor/assets/javascripts/task_list.js.coffee
+258
-0
No files found.
CHANGELOG
View file @
1311f8c2
...
...
@@ -44,6 +44,7 @@ v 8.8.4 (unreleased)
- Fix issue with arrow keys not working in search autocomplete dropdown
- Fix todos page throwing errors when you have a project pending deletion
- Reduce number of SQL queries when rendering user references
- Upgrade to jQuery 2
v 8.8.3
- Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312
...
...
app/assets/javascripts/application.js.coffee
View file @
1311f8c2
...
...
@@ -4,7 +4,7 @@
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
# the compiled file.
#
#= require jquery
#= require jquery
2
#= require jquery-ui/autocomplete
#= require jquery-ui/datepicker
#= require jquery-ui/draggable
...
...
app/assets/javascripts/awards_handler.coffee
View file @
1311f8c2
...
...
@@ -2,39 +2,47 @@ class @AwardsHandler
constructor
:
->
@
aliases
=
emojiAliases
()
@
aliases
=
gl
.
emojiAliases
()
$
(
document
)
.
off
'click'
,
'.js-add-award'
.
on
'click'
,
'.js-add-award'
,
(
event
)
=>
event
.
stopPropagation
()
event
.
preventDefault
()
.
on
'click'
,
'.js-add-award'
,
(
e
)
=>
e
.
stopPropagation
()
e
.
preventDefault
()
@
showEmojiMenu
$
(
e
.
currentTarget
)
$
(
'html'
).
on
'click'
,
(
e
)
->
$target
=
$
e
.
target
@
showEmojiMenu
$
(
event
.
currentTarget
)
unless
$target
.
closest
(
'.emoji-menu-content'
).
length
$
(
'.js-awards-block.current'
).
removeClass
'current'
$
(
'html'
).
on
'click'
,
(
event
)
->
unless
$
(
event
.
target
).
closest
(
'.emoji-menu'
).
length
unless
$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
)
=>
.
on
'click'
,
'.js-emoji-btn'
,
(
e
)
=>
e
.
preventDefault
()
emoji
=
$
(
e
.
currentTarget
).
find
(
'.icon'
).
data
'emoji'
@
getVotesBlock
().
addClass
'js-awards-block'
@
addAward
@
getAwardUrl
(),
emoji
$target
=
$
e
.
currentTarget
emoji
=
$target
.
find
(
'.icon'
).
data
'emoji'
$target
.
closest
(
'.js-awards-block'
).
addClass
'current'
@
addAward
@
getVotesBlock
(),
@
getAwardUrl
(),
emoji
showEmojiMenu
:
(
$addBtn
)
->
$menu
=
$
(
'.emoji-menu'
)
$menu
=
$
'.emoji-menu'
if
$addBtn
.
hasClass
'js-note-emoji'
$addBtn
.
parents
(
'.note'
).
find
(
'.js-awards-block'
).
addClass
'current'
else
$addBtn
.
closest
(
'.js-awards-block'
).
addClass
'current'
if
$menu
.
length
$holder
=
$addBtn
.
closest
(
'.js-award-holder'
)
...
...
@@ -51,7 +59,7 @@ class @AwardsHandler
$
(
'#emoji_search'
).
focus
()
else
$addBtn
.
addClass
'is-loading is-active'
url
=
$addBtn
.
data
'award-menu-url'
url
=
@
getAwardMenuUrl
()
@
createEmojiMenu
url
,
=>
$addBtn
.
removeClass
'is-loading'
...
...
@@ -68,12 +76,13 @@ class @AwardsHandler
createEmojiMenu
:
(
awardMenuUrl
,
callback
)
->
$
.
get
awardMenuUrl
,
(
response
)
=
>
$
.
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
...
...
@@ -91,88 +100,114 @@ class @AwardsHandler
$menu
.
css
(
css
)
addAward
:
(
awardUrl
,
emoji
,
checkMutuality
=
yes
)
->
addAward
:
(
votesBlock
,
awardUrl
,
emoji
,
checkMutuality
=
yes
,
callback
)
->
emoji
=
@
normilizeEmojiName
(
emoji
)
@
postEmoji
awardUrl
,
emoji
,
=>
@
addAwardToEmojiBar
(
emoji
,
checkMutuality
)
emoji
=
@
normilizeEmojiName
emoji
$
(
'.js-awards-block-current'
).
removeClass
'js-awards-block-current'
@
postEmoji
awardUrl
,
emoji
,
=>
@
addAwardToEmojiBar
votesBlock
,
emoji
,
checkMutuality
callback
?
()
$
(
'.emoji-menu'
).
removeClass
'is-visible'
addAwardToEmojiBar
:
(
emoji
,
checkForMutuality
=
yes
)
->
addAwardToEmojiBar
:
(
votesBlock
,
emoji
,
checkForMutuality
=
yes
)
->
@
checkMutuality
emoji
if
checkForMutuality
@
addEmojiToFrequentlyUsedList
(
emoji
)
@
checkMutuality
votesBlock
,
emoji
if
checkForMutuality
@
addEmojiToFrequentlyUsedList
emoji
emoji
=
@
normilizeEmojiName
(
emoji
)
$emojiB
tn
=
@
findEmojiIcon
(
emoji
).
parent
()
emoji
=
@
normilizeEmojiName
emoji
$emojiB
utton
=
@
findEmojiIcon
(
votesBlock
,
emoji
).
parent
()
if
$emojiB
t
n
.
length
>
0
if
@
isActive
(
$emojiBtn
)
@
decrementCounter
(
$emojiBtn
,
emoji
)
if
$emojiB
utto
n
.
length
>
0
if
@
isActive
$emojiButton
@
decrementCounter
$emojiButton
,
emoji
else
counter
=
$emojiBtn
.
find
(
'.js-counter'
)
counter
.
text
(
parseInt
(
counter
.
text
())
+
1
)
$emojiBtn
.
addClass
(
'active'
)
@
addMeToUserList
(
emoji
)
counter
=
$emojiButton
.
find
'.js-counter'
counter
.
text
parseInt
(
counter
.
text
())
+
1
$emojiButton
.
addClass
'active'
@
addMeToUserList
votesBlock
,
emoji
@
animateEmoji
$emojiButton
else
@
createEmoji
(
emoji
)
votesBlock
.
removeClass
'hidden'
@
createEmoji
votesBlock
,
emoji
getVotesBlock
:
->
getVotesBlock
:
->
return
$
'.awards.js-awards-block'
currentBlock
=
$
'.js-awards-block.current'
return
if
currentBlock
.
length
then
currentBlock
else
$
(
'.js-awards-block'
).
eq
0
getAwardUrl
:
->
@
getVotesBlock
().
data
'award-url'
getAwardUrl
:
->
return
@
getVotesBlock
().
data
'award-url'
checkMutuality
:
(
emoji
)
->
checkMutuality
:
(
votesBlock
,
emoji
)
->
awardUrl
=
@
getAwardUrl
()
if
emoji
in
[
'thumbsup'
,
'thumbsdown'
]
mutualVote
=
if
emoji
is
'thumbsup'
then
'thumbsdown'
else
'thumbsup'
$emojiButton
=
votesBlock
.
find
(
"[data-emoji=
#{
mutualVote
}
]"
).
parent
()
isAlreadyVoted
=
$emojiButton
.
hasClass
'active'
if
isAlreadyVoted
@
showEmojiLoader
$emojiButton
@
addAward
votesBlock
,
awardUrl
,
mutualVote
,
no
,
->
$emojiButton
.
removeClass
'is-loading'
showEmojiLoader
:
(
$emojiButton
)
->
$loader
=
$emojiButton
.
find
'.fa-spinner'
isAlreadyVoted
=
$
(
"[data-emoji=
#{
mutualVote
}
]"
).
parent
().
hasClass
'active'
@
addAward
awardUrl
,
mutualVote
,
no
if
isAlreadyVoted
unless
$loader
.
length
$emojiButton
.
append
'<i class="fa fa-spinner fa-spin award-control-icon award-control-icon-loading"></i>'
$emojiButton
.
addClass
'is-loading'
isActive
:
(
$emojiBtn
)
->
$emojiBtn
.
hasClass
'active'
isActive
:
(
$emojiButton
)
->
$emojiButton
.
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'
decrementCounter
:
(
$emojiButton
,
emoji
)
->
counter
=
$
'.js-counter'
,
$emojiButton
counterNumber
=
parseInt
counter
.
text
(),
10
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
)
counter
.
text
counterNumber
-
1
@
removeMeFromUserList
$emojiButton
,
emoji
else
if
emoji
is
'thumbsup'
or
emoji
is
'thumbsdown'
$emojiButton
.
tooltip
'destroy'
counter
.
text
'0'
@
removeMeFromUserList
$emojiButton
,
emoji
@
removeEmoji
$emojiButton
if
$emojiButton
.
parents
(
'.note'
).
length
else
$emojiBtn
.
tooltip
(
'destroy'
)
$emojiBtn
.
remove
()
@
removeEmoji
$emojiButton
$emojiButton
.
removeClass
'active'
removeEmoji
:
(
$emojiButton
)
->
$emojiButton
.
tooltip
(
'destroy'
)
$emojiButton
.
remove
()
$emojiBtn
.
removeClass
(
'active'
)
$votesBlock
=
@
getVotesBlock
()
if
$votesBlock
.
find
(
'.js-emoji-btn'
).
length
is
0
$votesBlock
.
addClass
'hidden'
getAwardTooltip
:
(
$awardBlock
)
->
return
$awardBlock
.
attr
(
'data-original-title'
)
or
$awardBlock
.
attr
(
'data-title'
)
return
$awardBlock
.
attr
(
'data-original-title'
)
or
$awardBlock
.
attr
(
'data-title'
)
or
''
removeMeFromUserList
:
(
$emojiB
t
n
,
emoji
)
->
removeMeFromUserList
:
(
$emojiB
utto
n
,
emoji
)
->
awardBlock
=
$emojiB
t
n
awardBlock
=
$emojiB
utto
n
originalTitle
=
@
getAwardTooltip
awardBlock
authors
=
originalTitle
.
split
', '
...
...
@@ -183,117 +218,134 @@ class @AwardsHandler
awardBlock
.
closest
'.js-emoji-btn'
.
removeData
'original-title'
.
removeData
'title'
.
attr
'data-original-title'
,
newAuthors
.
attr
'data-title'
,
newAuthors
@
resetTooltip
(
awardBlock
)
@
resetTooltip
awardBlock
addMeToUserList
:
(
emoji
)
->
addMeToUserList
:
(
votesBlock
,
emoji
)
->
awardBlock
=
@
findEmojiIcon
(
emoji
).
parent
()
awardBlock
=
@
findEmojiIcon
(
votesBlock
,
emoji
).
parent
()
origTitle
=
@
getAwardTooltip
awardBlock
users
=
[]
if
origTitle
users
=
origTitle
.
trim
().
split
(
', '
)
users
=
origTitle
.
trim
().
split
', '
users
.
push
(
'me'
)
awardBlock
.
attr
(
'title'
,
users
.
join
(
', '
))
users
.
push
'me'
awardBlock
.
attr
'title'
,
users
.
join
', '
@
resetTooltip
(
awardBlock
)
@
resetTooltip
awardBlock
resetTooltip
:
(
award
)
->
award
.
tooltip
(
'destroy'
)
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
cb
=
->
award
.
tooltip
()
setTimeout
cb
,
200
createEmoji_
:
(
emoji
)
->
createEmoji_
:
(
votesBlock
,
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)'
$emojiButton
=
$
buttonHtml
$emojiButton
.
insertBefore
votesBlock
.
find
'.js-award-holder'
.
find
'.emoji-icon'
.
data
'emoji'
,
emoji
@
animateEmoji
$emojiButton
$
(
'.award-control'
).
tooltip
()
votesBlock
.
removeClass
'current'
animateEmoji
:
(
$emoji
)
->
className
=
'pulse animated'
$currentBlock
=
$
'.js-awards-block'
$emoji
.
addClass
className
setTimeout
(
->
$emoji
.
removeClass
className
),
321
if
$currentBlock
.
is
'.hidden'
$currentBlock
.
removeClass
'hidden'
createEmoji
:
(
votesBlock
,
emoji
)
->
createEmoji
:
(
emoji
)
->
if
$
(
'.emoji-menu'
).
length
return
@
createEmoji_
votesBlock
,
emoji
return
@
createEmoji_
emoji
if
$
(
'.emoji-menu'
).
length
@
createEmojiMenu
@
getAwardMenuUrl
(),
=>
@
createEmoji_
votesBlock
,
emoji
awardMenuUrl
=
gl
.
awardMenuUrl
or
'/emojis'
@
createEmojiMenu
awardMenuUrl
,
=>
@
createEmoji
emoji
getAwardMenuUrl
:
->
return
gl
.
awardMenuUrl
resolveNameToCssClass
:
(
emoji
)
->
emoji
_icon
=
$
(
".emoji-menu-content [data-emoji='
#{
emoji
}
']"
)
emoji
Icon
=
$
".emoji-menu-content [data-emoji='
#{
emoji
}
']"
if
emoji
_i
con
.
length
>
0
unicodeName
=
emoji
_icon
.
data
(
'unicode-name'
)
if
emoji
I
con
.
length
>
0
unicodeName
=
emoji
Icon
.
data
'unicode-name'
else
# Find by alias
unicodeName
=
$
(
".emoji-menu-content [data-aliases*=':
#{
emoji
}
:']"
).
data
(
'unicode-name'
)
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
()
callback
()
if
data
.
ok
findEmojiIcon
:
(
votesBlock
,
emoji
)
->
return
votesBlock
.
find
".js-emoji-btn [data-emoji='
#{
emoji
}
']"
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
options
=
scrollTop
:
$
(
'.awards'
).
offset
().
top
-
110
$
(
'body, html'
).
animate
options
,
200
normilizeEmojiName
:
(
emoji
)
->
return
@
aliases
[
emoji
]
or
emoji
addEmojiToFrequentlyUsedList
:
(
emoji
)
->
frequently_used_emojis
=
@
getFrequentlyUsedEmojis
()
frequently_used_emojis
.
push
(
emoji
)
$
.
cookie
(
'frequently_used_emojis'
,
frequently_used_emojis
.
join
(
','
),
{
expires
:
365
})
frequentlyUsedEmojis
=
@
getFrequentlyUsedEmojis
()
frequentlyUsedEmojis
.
push
emoji
$
.
cookie
'frequently_used_emojis'
,
frequentlyUsedEmojis
.
join
(
','
),
{
expires
:
365
}
getFrequentlyUsedEmojis
:
->
frequently_used_emojis
=
(
$
.
cookie
(
'frequently_used_emojis'
)
||
''
).
split
(
','
)
_
.
compact
(
_
.
uniq
(
frequently_used_emojis
))
frequentlyUsedEmojis
=
(
$
.
cookie
(
'frequently_used_emojis'
)
or
''
).
split
(
','
)
return
_
.
compact
_
.
uniq
frequentlyUsedEmojis
renderFrequentlyUsedBlock
:
->
if
$
.
cookie
(
'frequently_used_emojis'
)
frequently_used_emojis
=
@
getFrequentlyUsedEmojis
()
if
$
.
cookie
'frequently_used_emojis'
frequentlyUsedEmojis
=
@
getFrequentlyUsedEmojis
()
ul
=
$
(
"<ul class='clearfix emoji-menu-list'>"
)
for
emoji
in
frequently
_used_e
mojis
for
emoji
in
frequently
UsedE
mojis
$
(
".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
()
...
...
@@ -310,5 +362,7 @@ class @AwardsHandler
else
$
(
'.emoji-menu-content'
).
children
().
show
()
searchEmojis
:
(
term
)
->
searchEmojis
:
(
term
)
->
$
(
".emoji-menu-content [data-emoji*='
#{
term
}
']"
).
closest
(
'li'
).
clone
()
app/assets/javascripts/dispatcher.js.coffee
View file @
1311f8c2
...
...
@@ -23,7 +23,7 @@ class Dispatcher
new
Issue
()
shortcut_handler
=
new
ShortcutsIssuable
()
new
ZenMode
()
window
.
awardsHandler
=
new
AwardsHandler
()
gl
.
awardsHandler
=
new
AwardsHandler
()
when
'projects:milestones:show'
,
'groups:milestones:show'
,
'dashboard:milestones:show'
new
Milestone
()
when
'dashboard:todos:index'
...
...
@@ -54,7 +54,7 @@ class Dispatcher
new
Diff
()
shortcut_handler
=
new
ShortcutsIssuable
(
true
)
new
ZenMode
()
window
.
awardsHandler
=
new
AwardsHandler
()
gl
.
awardsHandler
=
new
AwardsHandler
()
when
"projects:merge_requests:diffs"
new
Diff
()
new
ZenMode
()
...
...
app/assets/javascripts/due_date_select.js.coffee
View file @
1311f8c2
...
...
@@ -21,7 +21,7 @@ class @DueDateSelect
$dropdown
.
glDropdown
(
hidden
:
->
$selectbox
.
hide
()
$value
.
removeAttr
(
'style
'
)
$value
.
css
(
'display'
,
'
'
)
)
addDueDate
=
(
isDropdown
)
->
...
...
@@ -42,12 +42,13 @@ class @DueDateSelect
type
:
'PUT'
url
:
issueUpdateURL
data
:
data
dataType
:
'json'
beforeSend
:
->
$loading
.
fadeIn
()
if
isDropdown
$dropdown
.
trigger
(
'loading.gl.dropdown'
)
$selectbox
.
hide
()
$value
.
removeAttr
(
'style
'
)
$value
.
css
(
'display'
,
'
'
)
$valueContent
.
html
(
mediumDate
)
$sidebarValue
.
html
(
mediumDate
)
...
...
app/assets/javascripts/lib/emoji_aliases.js.coffee.erb
View file @
1311f8c2
window
.emojiAliases = ->
gl
.emojiAliases = ->
JSON.parse('
<%=
Gitlab
::
AwardEmoji
.
aliases
.
to_json
%>
')
app/assets/javascripts/milestone_select.js.coffee
View file @
1311f8c2
...
...
@@ -83,7 +83,7 @@ class @MilestoneSelect
$selectbox
.
hide
()
# display:block overrides the hide-collapse rule
$value
.
removeAttr
(
'style
'
)
$value
.
css
(
'display'
,
'
'
)
clicked
:
(
selected
)
->
page
=
$
(
'body'
).
data
'page'
isIssueIndex
=
page
is
'projects:issues:index'
...
...
@@ -118,7 +118,7 @@ class @MilestoneSelect
$dropdown
.
trigger
(
'loaded.gl.dropdown'
)
$loading
.
fadeOut
()
$selectbox
.
hide
()
$value
.
removeAttr
(
'style
'
)
$value
.
css
(
'display'
,
'
'
)
if
data
.
milestone
?
data
.
milestone
.
namespace
=
_this
.
currentProject
.
namespace
data
.
milestone
.
path
=
_this
.
currentProject
.
path
...
...
app/assets/javascripts/notes.js.coffee
View file @
1311f8c2
...
...
@@ -162,13 +162,14 @@ class @Notes
renderNote
:
(
note
)
->
unless
note
.
valid
if
note
.
award
flash
=
new
Flash
(
'You have already
used this award
emoji!'
,
'alert'
)
flash
=
new
Flash
(
'You have already
awarded this
emoji!'
,
'alert'
)
flash
.
pinTo
(
'.header-content'
)
return
if
note
.
award
awardsHandler
.
addAwardToEmojiBar
(
note
.
name
)
awardsHandler
.
scrollToAwards
()
votesBlock
=
$
(
'.js-awards-block'
).
eq
0
gl
.
awardsHandler
.
addAwardToEmojiBar
votesBlock
,
note
.
name
gl
.
awardsHandler
.
scrollToAwards
()
# render note if it not present in loaded list
# or skip if rendered
...
...
app/assets/javascripts/users_select.js.coffee
View file @
1311f8c2
...
...
@@ -149,7 +149,7 @@ class @UsersSelect
hidden
:
(
e
)
->
$selectbox
.
hide
()
# display:block overrides the hide-collapse rule
$value
.
removeAttr
(
'style
'
)
$value
.
css
(
'display'
,
'
'
)
clicked
:
(
user
)
->
page
=
$
(
'body'
).
data
'page'
...
...
app/assets/stylesheets/framework/timeline.scss
View file @
1311f8c2
...
...
@@ -5,7 +5,7 @@
padding
:
0
;
.timeline-entry
{
padding
:
$gl-padding
$gl-btn-padding
;
padding
:
$gl-padding
$gl-btn-padding
11px
;
border-color
:
$table-border-color
;
color
:
$gl-gray
;
border-bottom
:
1px
solid
$border-white-light
;
...
...
app/assets/stylesheets/pages/awards.scss
View file @
1311f8c2
...
...
@@ -95,6 +95,7 @@
.award-control
{
margin-right
:
5px
;
margin-bottom
:
5px
;
padding-left
:
5px
;
padding-right
:
5px
;
line-height
:
20px
;
...
...
@@ -108,7 +109,8 @@
}
&
.is-loading
{
.award-control-icon-normal
{
.award-control-icon-normal
,
.emoji-icon
{
display
:
none
;
}
...
...
app/assets/stylesheets/pages/notes.scss
View file @
1311f8c2
...
...
@@ -69,6 +69,10 @@ ul.notes {
.note-edit-form
{
display
:
block
;
&
.current-note-edit-form
+
.note-awards
{
display
:
none
;
}
}
}
...
...
@@ -116,10 +120,38 @@ ul.notes {
}
}
.note-awards
{
.js-awards-block
{
padding
:
2px
;
margin-top
:
10px
;
}
.award-control
{
font-size
:
13px
;
padding
:
2px
5px
;
}
}
.note-header
{
padding-bottom
:
3px
;
}
.note-emoji-button
{
.fa-spinner
{
display
:
none
;
}
&
.is-loading
{
.fa-smile-o
{
display
:
none
;
}
.fa-spinner
{
display
:
inline-block
;
}
}
}
}
}
...
...
app/controllers/concerns/toggle_award_emoji.rb
View file @
1311f8c2
...
...
@@ -9,13 +9,22 @@ module ToggleAwardEmoji
name
=
params
.
require
(
:name
)
awardable
.
toggle_award_emoji
(
name
,
current_user
)
TodoService
.
new
.
new_award_emoji
(
awardable
,
current_user
)
TodoService
.
new
.
new_award_emoji
(
to_todoable
(
awardable
)
,
current_user
)
render
json:
{
ok:
true
}
end
private
def
to_todoable
(
awardable
)
case
awardable
when
Note
awardable
.
noteable
else
awardable
end
end
def
awardable
raise
NotImplementedError
end
...
...
app/controllers/projects/notes_controller.rb
View file @
1311f8c2
class
Projects::NotesController
<
Projects
::
ApplicationController
include
ToggleAwardEmoji
# Authorize
before_action
:authorize_read_note!
before_action
:authorize_create_note!
,
only:
[
:create
]
...
...
@@ -61,6 +63,7 @@ class Projects::NotesController < Projects::ApplicationController
def
note
@note
||=
@project
.
notes
.
find
(
params
[
:id
])
end
alias_method
:awardable
,
:note
def
note_to_html
(
note
)
render_to_string
(
...
...
app/models/note.rb
View file @
1311f8c2
...
...
@@ -3,6 +3,7 @@ class Note < ActiveRecord::Base
include
Gitlab
::
CurrentSettings
include
Participable
include
Mentionable
include
Awardable
default_value_for
:system
,
false
...
...
app/views/award_emoji/_awards_block.html.haml
View file @
1311f8c2
...
...
@@ -11,7 +11,7 @@
gl
.
awardMenuUrl
=
"
#{
emojis_path
}
"
.award-menu-holder.js-award-holder
%button
.btn.award-control.js-add-award
{
type:
"button"
,
data:
{
award_menu_url:
emojis_path
}
}
%button
.btn.award-control.js-add-award
{
type:
"button"
}
=
icon
(
'smile-o'
,
class:
"award-control-icon award-control-icon-normal"
)
=
icon
(
'spinner spin'
,
class:
"award-control-icon award-control-icon-loading"
)
%span
.award-control-text
...
...
app/views/projects/issues/show.html.haml
View file @
1311f8c2
app/views/projects/notes/_note.html.haml
View file @
1311f8c2
...
...
@@ -22,6 +22,9 @@
%span
.note-role
=
access
-
if
note_editable
=
link_to
'#'
,
title:
'Award Emoji'
,
class:
'note-action-button note-emoji-button js-add-award js-note-emoji'
,
data:
{
position:
'right'
}
do
=
icon
(
'spinner spin'
)
=
icon
(
'smile-o'
)
=
link_to
'#'
,
title:
'Edit comment'
,
class:
'note-action-button js-note-edit'
do
=
icon
(
'pencil'
)
=
link_to
namespace_project_note_path
(
note
.
project
.
namespace
,
note
.
project
,
note
),
title:
'Remove comment'
,
method: :delete
,
data:
{
confirm:
'Are you sure you want to remove this comment?'
},
remote:
true
,
class:
'note-action-button js-note-delete danger'
do
...
...
@@ -30,9 +33,11 @@
.note-text
=
preserve
do
=
markdown
(
note
.
note
,
pipeline: :note
,
cache_key:
[
note
,
"note"
],
author:
note
.
author
)
=
edited_time_ago_with_tooltip
(
note
,
placement:
'bottom'
,
html_class:
'note_edited_ago'
,
include_author:
true
)
-
if
note_editable
=
render
'projects/notes/edit_form'
,
note:
note
=
edited_time_ago_with_tooltip
(
note
,
placement:
'bottom'
,
html_class:
'note_edited_ago'
,
include_author:
true
)
.note-awards
=
render
'award_emoji/awards_block'
,
awardable:
note
,
inline:
false
-
if
note
.
attachment
.
url
.note-attachment
...
...
config/routes.rb
View file @
1311f8c2
...
...
@@ -758,6 +758,7 @@ Rails.application.routes.draw do
resources
:notes
,
only:
[
:index
,
:create
,
:destroy
,
:update
],
constraints:
{
id:
/\d+/
}
do
member
do
post
:toggle_award_emoji
delete
:delete_attachment
end
end
...
...
spec/controllers/projects/notes_controller_spec.rb
0 → 100644
View file @
1311f8c2
require
(
'spec_helper'
)
describe
Projects
::
NotesController
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:note
)
{
create
(
:note
,
noteable:
issue
,
project:
project
)
}
describe
'POST #toggle_award_emoji'
do
before
do
sign_in
(
user
)
project
.
team
<<
[
user
,
:developer
]
end
it
"toggles the award emoji"
do
expect
do
post
(
:toggle_award_emoji
,
namespace_id:
project
.
namespace
.
path
,
project_id:
project
.
path
,
id:
note
.
id
,
name:
"thumbsup"
)
end
.
to
change
{
note
.
award_emoji
.
count
}.
by
(
1
)
expect
(
response
.
status
).
to
eq
(
200
)
end
it
"removes the already awarded emoji"
do
post
(
:toggle_award_emoji
,
namespace_id:
project
.
namespace
.
path
,
project_id:
project
.
path
,
id:
note
.
id
,
name:
"thumbsup"
)
expect
do
post
(
:toggle_award_emoji
,
namespace_id:
project
.
namespace
.
path
,
project_id:
project
.
path
,
id:
note
.
id
,
name:
"thumbsup"
)
end
.
to
change
{
AwardEmoji
.
count
}.
by
(
-
1
)
expect
(
response
.
status
).
to
eq
(
200
)
end
end
end
spec/features/issues_spec.rb
View file @
1311f8c2
...
...
@@ -365,13 +365,9 @@ describe 'Issues', feature: true do
page
.
within
(
'.assignee'
)
do
expect
(
page
).
to
have_content
"
#{
@user
.
name
}
"
end
find
(
'.block.assignee .edit-link'
).
click
sleep
2
# wait for ajax stuff to complete
first
(
'.dropdown-menu-user-link'
).
click
sleep
2
page
.
within
(
'.assignee'
)
do
click_link
'Edit'
click_link
'Unassigned'
expect
(
page
).
to
have_content
'No assignee'
end
...
...
spec/javascripts/awards_handler_spec.js.coffee
0 → 100644
View file @
1311f8c2
#= require awards_handler
#= require jquery
#= require jquery.cookie
#= require ./fixtures/emoji_menu
awardsHandler
=
null
window
.
gl
or=
{}
gl
.
emojiAliases
=
->
return
{
'+1'
:
'thumbsup'
,
'-1'
:
'thumbsdown'
}
gl
.
awardMenuUrl
=
'/emojis'
lazyAssert
=
(
done
,
assertFn
)
->
setTimeout
->
# Maybe jasmine.clock here?
assertFn
()
done
()
,
333
describe
'AwardsHandler'
,
->
fixture
.
preload
'awards_handler.html'
beforeEach
->
fixture
.
load
'awards_handler.html'
awardsHandler
=
new
AwardsHandler
spyOn
(
awardsHandler
,
'postEmoji'
).
and
.
callFake
(
url
,
emoji
,
cb
)
=>
cb
()
spyOn
(
jQuery
,
'get'
).
and
.
callFake
(
req
,
cb
)
->
expect
(
req
).
toBe
'/emojis'
cb
window
.
emojiMenu
describe
'::showEmojiMenu'
,
->
it
'should show emoji menu when Add emoji button clicked'
,
(
done
)
->
$
(
'.js-add-award'
).
eq
(
0
).
click
()
lazyAssert
done
,
->
$emojiMenu
=
$
'.emoji-menu'
expect
(
$emojiMenu
.
length
).
toBe
1
expect
(
$emojiMenu
.
hasClass
(
'is-visible'
)).
toBe
yes
expect
(
$emojiMenu
.
find
(
'#emoji_search'
).
length
).
toBe
1
expect
(
$
(
'.js-awards-block.current'
).
length
).
toBe
1
it
'should also show emoji menu for the smiley icon in notes'
,
(
done
)
->
$
(
'.note-action-button'
).
click
()
lazyAssert
done
,
->
$emojiMenu
=
$
'.emoji-menu'
expect
(
$emojiMenu
.
length
).
toBe
1
it
'should remove emoji menu when body is clicked'
,
(
done
)
->
$
(
'.js-add-award'
).
eq
(
0
).
click
()
lazyAssert
done
,
->
$emojiMenu
=
$
(
'.emoji-menu'
)
$
(
'body'
).
click
()
expect
(
$emojiMenu
.
length
).
toBe
1
expect
(
$emojiMenu
.
hasClass
(
'is-visible'
)).
toBe
no
expect
(
$
(
'.js-awards-block.current'
).
length
).
toBe
0
describe
'::addAwardToEmojiBar'
,
->
it
'should add emoji to votes block'
,
->
$votesBlock
=
$
(
'.js-awards-block'
).
eq
0
awardsHandler
.
addAwardToEmojiBar
$votesBlock
,
'heart'
,
no
$emojiButton
=
$votesBlock
.
find
'[data-emoji=heart]'
expect
(
$emojiButton
.
length
).
toBe
1
expect
(
$emojiButton
.
next
(
'.js-counter'
).
text
()).
toBe
'1'
expect
(
$votesBlock
.
hasClass
(
'hidden'
)).
toBe
no
it
'should remove the emoji when we click again'
,
->
$votesBlock
=
$
(
'.js-awards-block'
).
eq
0
awardsHandler
.
addAwardToEmojiBar
$votesBlock
,
'heart'
,
no
awardsHandler
.
addAwardToEmojiBar
$votesBlock
,
'heart'
,
no
$emojiButton
=
$votesBlock
.
find
'[data-emoji=heart]'
expect
(
$emojiButton
.
length
).
toBe
0
it
'should decrement the emoji counter'
,
->
$votesBlock
=
$
(
'.js-awards-block'
).
eq
0
awardsHandler
.
addAwardToEmojiBar
$votesBlock
,
'heart'
,
no
$emojiButton
=
$votesBlock
.
find
'[data-emoji=heart]'
$emojiButton
.
next
(
'.js-counter'
).
text
5
awardsHandler
.
addAwardToEmojiBar
$votesBlock
,
'heart'
,
no
expect
(
$emojiButton
.
length
).
toBe
1
expect
(
$emojiButton
.
next
(
'.js-counter'
).
text
()).
toBe
'4'
describe
'::getAwardUrl'
,
->
it
'should return the url for request'
,
->
expect
(
awardsHandler
.
getAwardUrl
()).
toBe
'/gitlab-org/gitlab-test/issues/8/toggle_award_emoji'
describe
'::addAward and ::checkMutuality'
,
->
it
'should handle :+1: and :-1: mutuality'
,
->
awardUrl
=
awardsHandler
.
getAwardUrl
()
$votesBlock
=
$
(
'.js-awards-block'
).
eq
0
$thumbsUpEmoji
=
$votesBlock
.
find
(
'[data-emoji=thumbsup]'
).
parent
()
$thumbsDownEmoji
=
$votesBlock
.
find
(
'[data-emoji=thumbsdown]'
).
parent
()
awardsHandler
.
addAward
$votesBlock
,
awardUrl
,
'thumbsup'
,
no
expect
(
$thumbsUpEmoji
.
hasClass
(
'active'
)).
toBe
yes
expect
(
$thumbsDownEmoji
.
hasClass
(
'active'
)).
toBe
no
$thumbsUpEmoji
.
tooltip
()
$thumbsDownEmoji
.
tooltip
()
awardsHandler
.
addAward
$votesBlock
,
awardUrl
,
'thumbsdown'
,
yes
expect
(
$thumbsUpEmoji
.
hasClass
(
'active'
)).
toBe
no
expect
(
$thumbsDownEmoji
.
hasClass
(
'active'
)).
toBe
yes
describe
'::removeEmoji'
,
->
it
'should remove emoji'
,
->
awardUrl
=
awardsHandler
.
getAwardUrl
()
$votesBlock
=
$
(
'.js-awards-block'
).
eq
0
awardsHandler
.
addAward
$votesBlock
,
awardUrl
,
'fire'
,
no
expect
(
$votesBlock
.
find
(
'[data-emoji=fire]'
).
length
).
toBe
1
awardsHandler
.
removeEmoji
$votesBlock
.
find
(
'[data-emoji=fire]'
).
closest
(
'button'
)
expect
(
$votesBlock
.
find
(
'[data-emoji=fire]'
).
length
).
toBe
0
describe
'search'
,
->
it
'should filter the emoji'
,
->
$
(
'.js-add-award'
).
eq
(
0
).
click
()
expect
(
$
(
'[data-emoji=angel]'
).
is
(
':visible'
)).
toBe
yes
expect
(
$
(
'[data-emoji=anger]'
).
is
(
':visible'
)).
toBe
yes
$
(
'#emoji_search'
).
val
(
'ali'
).
trigger
'keyup'
expect
(
$
(
'[data-emoji=angel]'
).
is
(
':visible'
)).
toBe
no
expect
(
$
(
'[data-emoji=anger]'
).
is
(
':visible'
)).
toBe
no
expect
(
$
(
'[data-emoji=alien]'
).
is
(
':visible'
)).
toBe
yes
expect
(
$
(
'h5.emoji-search'
).
is
(
':visible'
)).
toBe
yes
describe
'emoji menu'
,
->
selector
=
'[data-emoji=sunglasses]'
openEmojiMenuAndAddEmoji
=
->
$
(
'.js-add-award'
).
eq
(
0
).
click
()
$menu
=
$
'.emoji-menu'
$block
=
$
'.js-awards-block'
$emoji
=
$menu
.
find
".emoji-menu-list-item
#{
selector
}
"
expect
(
$emoji
.
length
).
toBe
1
expect
(
$block
.
find
(
selector
).
length
).
toBe
0
$emoji
.
click
()
expect
(
$menu
.
hasClass
(
'.is-visible'
)).
toBe
no
expect
(
$block
.
find
(
selector
).
length
).
toBe
1
it
'should add selected emoji to awards block'
,
->
openEmojiMenuAndAddEmoji
()
it
'should remove already selected emoji'
,
->
openEmojiMenuAndAddEmoji
()
$
(
'.js-add-award'
).
eq
(
0
).
click
()
$block
=
$
'.js-awards-block'
$emoji
=
$
(
'.emoji-menu'
).
find
".emoji-menu-list-item
#{
selector
}
"
$emoji
.
click
()
expect
(
$block
.
find
(
selector
).
length
).
toBe
0
spec/javascripts/behaviors/quick_submit_spec.js.coffee
View file @
1311f8c2
...
...
@@ -14,17 +14,17 @@ describe 'Quick Submit behavior', ->
}
it
'does not respond to other keyCodes'
,
->
$
(
'input'
).
trigger
(
keydownEvent
(
keyCode
:
32
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
keyCode
:
32
))
expect
(
@
spies
.
submit
).
not
.
toHaveBeenTriggered
()
it
'does not respond to Enter alone'
,
->
$
(
'input'
).
trigger
(
keydownEvent
(
ctrlKey
:
false
,
metaKey
:
false
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
ctrlKey
:
false
,
metaKey
:
false
))
expect
(
@
spies
.
submit
).
not
.
toHaveBeenTriggered
()
it
'does not respond to repeated events'
,
->
$
(
'input'
).
trigger
(
keydownEvent
(
repeat
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
repeat
:
true
))
expect
(
@
spies
.
submit
).
not
.
toHaveBeenTriggered
()
...
...
@@ -38,26 +38,26 @@ describe 'Quick Submit behavior', ->
# only run the tests that apply to the current platform
if
navigator
.
userAgent
.
match
(
/Macintosh/
)
it
'responds to Meta+Enter'
,
->
$
(
'input'
).
trigger
(
keydownEvent
())
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
())
expect
(
@
spies
.
submit
).
toHaveBeenTriggered
()
it
'excludes other modifier keys'
,
->
$
(
'input'
).
trigger
(
keydownEvent
(
altKey
:
true
))
$
(
'input'
).
trigger
(
keydownEvent
(
ctrlKey
:
true
))
$
(
'input'
).
trigger
(
keydownEvent
(
shiftKey
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
altKey
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
ctrlKey
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
shiftKey
:
true
))
expect
(
@
spies
.
submit
).
not
.
toHaveBeenTriggered
()
else
it
'responds to Ctrl+Enter'
,
->
$
(
'input'
).
trigger
(
keydownEvent
())
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
())
expect
(
@
spies
.
submit
).
toHaveBeenTriggered
()
it
'excludes other modifier keys'
,
->
$
(
'input'
).
trigger
(
keydownEvent
(
altKey
:
true
))
$
(
'input'
).
trigger
(
keydownEvent
(
metaKey
:
true
))
$
(
'input'
).
trigger
(
keydownEvent
(
shiftKey
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
altKey
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
metaKey
:
true
))
$
(
'input
.quick-submit-input
'
).
trigger
(
keydownEvent
(
shiftKey
:
true
))
expect
(
@
spies
.
submit
).
not
.
toHaveBeenTriggered
()
...
...
spec/javascripts/fixtures/awards_handler.html.haml
0 → 100644
View file @
1311f8c2
.issue-details.issuable-details
.detail-page-description.content-block
%h2
.title
Quibusdam sint officiis earum molestiae ipsa autem voluptatem nisi rem.
.description.js-task-list-container.is-task-list-enabled
.wiki
%p
Qui exercitationem magnam optio quae fuga earum odio.
%textarea
.hidden.js-task-list-field
Qui exercitationem magnam optio quae fuga earum odio.
%small
.edited-text
.content-block.content-block-small
.awards.js-awards-block
{
"data-award-url"
=>
"/gitlab-org/gitlab-test/issues/8/toggle_award_emoji"
}
%button
.award-control.btn.js-emoji-btn
{
"data-placement"
=>
"bottom"
,
"data-title"
=>
""
,
:type
=>
"button"
}
.icon.emoji-icon.emoji-1F44D
{
"data-aliases"
=>
""
,
"data-emoji"
=>
"thumbsup"
,
"data-unicode-name"
=>
"1F44D"
,
:title
=>
"thumbsup"
}
%span
.award-control-text.js-counter
0
%button
.award-control.btn.js-emoji-btn
{
"data-placement"
=>
"bottom"
,
"data-title"
=>
""
,
:type
=>
"button"
}
.icon.emoji-icon.emoji-1F44E
{
"data-aliases"
=>
""
,
"data-emoji"
=>
"thumbsdown"
,
"data-unicode-name"
=>
"1F44E"
,
:title
=>
"thumbsdown"
}
%span
.award-control-text.js-counter
0
.award-menu-holder.js-award-holder
%button
.btn.award-control.js-add-award
{
:type
=>
"button"
}
%i
.fa.fa-smile-o.award-control-icon.award-control-icon-normal
%i
.fa.fa-spinner.fa-spin.award-control-icon.award-control-icon-loading
%span
.award-control-text
Add
%section
.issuable-discussion
#notes
%ul
#notes-list
.notes.main-notes-list.timeline
%li
#note_348
.note.note-row-348.timeline-entry
{
"data-author-id"
=>
"18"
,
"data-editable"
=>
""
}
.timeline-entry-inner
.timeline-icon
%a
{
:href
=>
"/u/agustin"
}
%img
.avatar.s40
{
:alt
=>
""
,
:src
=>
"#"
}
/
.timeline-content
.note-header
%a
.author_link
{
:href
=>
"/u/agustin"
}
%span
.author
Brenna Stokes
.inline.note-headline-light
@agustin commented
%a
{
:href
=>
"#note_348"
}
%time
11 days ago
.note-actions
%span
.note-role
Reporter
%a
.note-action-button.note-emoji-button.js-add-award.js-note-emoji
{
"data-position"
=>
"right"
,
:href
=>
"#"
,
:title
=>
"Award Emoji"
}
%i
.fa.fa-spinner.fa-spin
%i
.fa.fa-smile-o
.js-task-list-container.note-body.is-task-list-enabled
.note-text
%p
Suscipit sunt quia quisquam sed eveniet ipsam.
.note-awards
.awards.hidden.js-awards-block
{
"data-award-url"
=>
"/gitlab-org/gitlab-test/notes/348/toggle_award_emoji"
}
.award-menu-holder.js-award-holder
%button
.btn.award-control.js-add-award
{
:type
=>
"button"
}
%i
.fa.fa-smile-o.award-control-icon.award-control-icon-normal
%i
.fa.fa-spinner.fa-spin.award-control-icon.award-control-icon-loading
%span
.award-control-text
Add
spec/javascripts/fixtures/behaviors/quick_submit.html.haml
View file @
1311f8c2
%form
.js-quick-submit
{
action:
'/foo'
}
%input
{
type:
'text'
}
%input
{
type:
'text'
,
class:
'quick-submit-input'
}
%textarea
%input
{
type:
'submit'
}
Submit
...
...
spec/javascripts/fixtures/emoji_menu.coffee
0 → 100644
View file @
1311f8c2
window
.
emojiMenu
=
"""
<div class='emoji-menu'>
<div class='emoji-menu-content'>
<input type="text" name="emoji_search" id="emoji_search" value="" class="emoji-search search-input form-control" />
<h5 class='emoji-menu-title'>
Emoticons
</h5>
<ul class='clearfix emoji-menu-list'>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F47D" title="alien" data-aliases="" data-emoji="alien" data-unicode-name="1F47D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F47C" title="angel" data-aliases="" data-emoji="angel" data-unicode-name="1F47C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A2" title="anger" data-aliases="" data-emoji="anger" data-unicode-name="1F4A2"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F620" title="angry" data-aliases="" data-emoji="angry" data-unicode-name="1F620"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F627" title="anguished" data-aliases="" data-emoji="anguished" data-unicode-name="1F627"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F632" title="astonished" data-aliases="" data-emoji="astonished" data-unicode-name="1F632"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F45F" title="athletic_shoe" data-aliases="" data-emoji="athletic_shoe" data-unicode-name="1F45F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F476" title="baby" data-aliases="" data-emoji="baby" data-unicode-name="1F476"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F459" title="bikini" data-aliases="" data-emoji="bikini" data-unicode-name="1F459"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F499" title="blue_heart" data-aliases="" data-emoji="blue_heart" data-unicode-name="1F499"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F60A" title="blush" data-aliases="" data-emoji="blush" data-unicode-name="1F60A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A5" title="boom" data-aliases="" data-emoji="boom" data-unicode-name="1F4A5"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F462" title="boot" data-aliases="" data-emoji="boot" data-unicode-name="1F462"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F647" title="bow" data-aliases="" data-emoji="bow" data-unicode-name="1F647"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F466" title="boy" data-aliases="" data-emoji="boy" data-unicode-name="1F466"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F470" title="bride_with_veil" data-aliases="" data-emoji="bride_with_veil" data-unicode-name="1F470"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4BC" title="briefcase" data-aliases="" data-emoji="briefcase" data-unicode-name="1F4BC"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F494" title="broken_heart" data-aliases="" data-emoji="broken_heart" data-unicode-name="1F494"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F464" title="bust_in_silhouette" data-aliases="" data-emoji="bust_in_silhouette" data-unicode-name="1F464"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F465" title="busts_in_silhouette" data-aliases="" data-emoji="busts_in_silhouette" data-unicode-name="1F465"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F44F" title="clap" data-aliases="" data-emoji="clap" data-unicode-name="1F44F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F302" title="closed_umbrella" data-aliases="" data-emoji="closed_umbrella" data-unicode-name="1F302"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F630" title="cold_sweat" data-aliases="" data-emoji="cold_sweat" data-unicode-name="1F630"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F616" title="confounded" data-aliases="" data-emoji="confounded" data-unicode-name="1F616"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F615" title="confused" data-aliases="" data-emoji="confused" data-unicode-name="1F615"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F477" title="construction_worker" data-aliases="" data-emoji="construction_worker" data-unicode-name="1F477"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F46E" title="cop" data-aliases="" data-emoji="cop" data-unicode-name="1F46E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F46B" title="couple" data-aliases="" data-emoji="couple" data-unicode-name="1F46B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F491" title="couple_with_heart" data-aliases="" data-emoji="couple_with_heart" data-unicode-name="1F491"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F48F" title="couplekiss" data-aliases="" data-emoji="couplekiss" data-unicode-name="1F48F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F451" title="crown" data-aliases="" data-emoji="crown" data-unicode-name="1F451"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F622" title="cry" data-aliases="" data-emoji="cry" data-unicode-name="1F622"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F63F" title="crying_cat_face" data-aliases="" data-emoji="crying_cat_face" data-unicode-name="1F63F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F498" title="cupid" data-aliases="" data-emoji="cupid" data-unicode-name="1F498"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F483" title="dancer" data-aliases="" data-emoji="dancer" data-unicode-name="1F483"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F46F" title="dancers" data-aliases="" data-emoji="dancers" data-unicode-name="1F46F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A8" title="dash" data-aliases="" data-emoji="dash" data-unicode-name="1F4A8"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F61E" title="disappointed" data-aliases="" data-emoji="disappointed" data-unicode-name="1F61E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F625" title="disappointed_relieved" data-aliases="" data-emoji="disappointed_relieved" data-unicode-name="1F625"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4AB" title="dizzy" data-aliases="" data-emoji="dizzy" data-unicode-name="1F4AB"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F635" title="dizzy_face" data-aliases="" data-emoji="dizzy_face" data-unicode-name="1F635"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F457" title="dress" data-aliases="" data-emoji="dress" data-unicode-name="1F457"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A7" title="droplet" data-aliases="" data-emoji="droplet" data-unicode-name="1F4A7"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F442" title="ear" data-aliases="" data-emoji="ear" data-unicode-name="1F442"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F611" title="expressionless" data-aliases="" data-emoji="expressionless" data-unicode-name="1F611"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F453" title="eyeglasses" data-aliases="" data-emoji="eyeglasses" data-unicode-name="1F453"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F440" title="eyes" data-aliases="" data-emoji="eyes" data-unicode-name="1F440"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F46A" title="family" data-aliases="" data-emoji="family" data-unicode-name="1F46A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F628" title="fearful" data-aliases="" data-emoji="fearful" data-unicode-name="1F628"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F525" title="fire" data-aliases=":flame:" data-emoji="fire" data-unicode-name="1F525"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-270A" title="fist" data-aliases="" data-emoji="fist" data-unicode-name="270A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F633" title="flushed" data-aliases="" data-emoji="flushed" data-unicode-name="1F633"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F463" title="footprints" data-aliases="" data-emoji="footprints" data-unicode-name="1F463"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F626" title="frowning" data-aliases=":anguished:" data-emoji="frowning" data-unicode-name="1F626"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F48E" title="gem" data-aliases="" data-emoji="gem" data-unicode-name="1F48E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F467" title="girl" data-aliases="" data-emoji="girl" data-unicode-name="1F467"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F49A" title="green_heart" data-aliases="" data-emoji="green_heart" data-unicode-name="1F49A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F62C" title="grimacing" data-aliases="" data-emoji="grimacing" data-unicode-name="1F62C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F601" title="grin" data-aliases="" data-emoji="grin" data-unicode-name="1F601"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F600" title="grinning" data-aliases="" data-emoji="grinning" data-unicode-name="1F600"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F482" title="guardsman" data-aliases="" data-emoji="guardsman" data-unicode-name="1F482"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F487" title="haircut" data-aliases="" data-emoji="haircut" data-unicode-name="1F487"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F45C" title="handbag" data-aliases="" data-emoji="handbag" data-unicode-name="1F45C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F649" title="hear_no_evil" data-aliases="" data-emoji="hear_no_evil" data-unicode-name="1F649"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-2764" title="heart" data-aliases="" data-emoji="heart" data-unicode-name="2764"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F60D" title="heart_eyes" data-aliases="" data-emoji="heart_eyes" data-unicode-name="1F60D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F63B" title="heart_eyes_cat" data-aliases="" data-emoji="heart_eyes_cat" data-unicode-name="1F63B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F493" title="heartbeat" data-aliases="" data-emoji="heartbeat" data-unicode-name="1F493"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F497" title="heartpulse" data-aliases="" data-emoji="heartpulse" data-unicode-name="1F497"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F460" title="high_heel" data-aliases="" data-emoji="high_heel" data-unicode-name="1F460"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F62F" title="hushed" data-aliases="" data-emoji="hushed" data-unicode-name="1F62F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F47F" title="imp" data-aliases="" data-emoji="imp" data-unicode-name="1F47F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F481" title="information_desk_person" data-aliases="" data-emoji="information_desk_person" data-unicode-name="1F481"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F607" title="innocent" data-aliases="" data-emoji="innocent" data-unicode-name="1F607"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F47A" title="japanese_goblin" data-aliases="" data-emoji="japanese_goblin" data-unicode-name="1F47A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F479" title="japanese_ogre" data-aliases="" data-emoji="japanese_ogre" data-unicode-name="1F479"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F456" title="jeans" data-aliases="" data-emoji="jeans" data-unicode-name="1F456"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F602" title="joy" data-aliases="" data-emoji="joy" data-unicode-name="1F602"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F639" title="joy_cat" data-aliases="" data-emoji="joy_cat" data-unicode-name="1F639"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F458" title="kimono" data-aliases="" data-emoji="kimono" data-unicode-name="1F458"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F48B" title="kiss" data-aliases="" data-emoji="kiss" data-unicode-name="1F48B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F617" title="kissing" data-aliases="" data-emoji="kissing" data-unicode-name="1F617"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F63D" title="kissing_cat" data-aliases="" data-emoji="kissing_cat" data-unicode-name="1F63D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F61A" title="kissing_closed_eyes" data-aliases="" data-emoji="kissing_closed_eyes" data-unicode-name="1F61A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F618" title="kissing_heart" data-aliases="" data-emoji="kissing_heart" data-unicode-name="1F618"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F619" title="kissing_smiling_eyes" data-aliases="" data-emoji="kissing_smiling_eyes" data-unicode-name="1F619"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F606" title="laughing" data-aliases=":satisfied:" data-emoji="laughing" data-unicode-name="1F606"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F444" title="lips" data-aliases="" data-emoji="lips" data-unicode-name="1F444"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F484" title="lipstick" data-aliases="" data-emoji="lipstick" data-unicode-name="1F484"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F48C" title="love_letter" data-aliases="" data-emoji="love_letter" data-unicode-name="1F48C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F468" title="man" data-aliases="" data-emoji="man" data-unicode-name="1F468"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F472" title="man_with_gua_pi_mao" data-aliases="" data-emoji="man_with_gua_pi_mao" data-unicode-name="1F472"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F473" title="man_with_turban" data-aliases="" data-emoji="man_with_turban" data-unicode-name="1F473"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F45E" title="mans_shoe" data-aliases="" data-emoji="mans_shoe" data-unicode-name="1F45E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F637" title="mask" data-aliases="" data-emoji="mask" data-unicode-name="1F637"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F486" title="massage" data-aliases="" data-emoji="massage" data-unicode-name="1F486"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4AA" title="muscle" data-aliases="" data-emoji="muscle" data-unicode-name="1F4AA"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F485" title="nail_care" data-aliases="" data-emoji="nail_care" data-unicode-name="1F485"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F454" title="necktie" data-aliases="" data-emoji="necktie" data-unicode-name="1F454"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F610" title="neutral_face" data-aliases="" data-emoji="neutral_face" data-unicode-name="1F610"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F645" title="no_good" data-aliases="" data-emoji="no_good" data-unicode-name="1F645"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F636" title="no_mouth" data-aliases="" data-emoji="no_mouth" data-unicode-name="1F636"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F443" title="nose" data-aliases="" data-emoji="nose" data-unicode-name="1F443"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F44C" title="ok_hand" data-aliases="" data-emoji="ok_hand" data-unicode-name="1F44C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F646" title="ok_woman" data-aliases="" data-emoji="ok_woman" data-unicode-name="1F646"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F474" title="older_man" data-aliases="" data-emoji="older_man" data-unicode-name="1F474"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F475" title="older_woman" data-aliases=":grandma:" data-emoji="older_woman" data-unicode-name="1F475"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F450" title="open_hands" data-aliases="" data-emoji="open_hands" data-unicode-name="1F450"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F62E" title="open_mouth" data-aliases="" data-emoji="open_mouth" data-unicode-name="1F62E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F614" title="pensive" data-aliases="" data-emoji="pensive" data-unicode-name="1F614"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F623" title="persevere" data-aliases="" data-emoji="persevere" data-unicode-name="1F623"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F64D" title="person_frowning" data-aliases="" data-emoji="person_frowning" data-unicode-name="1F64D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F471" title="person_with_blond_hair" data-aliases="" data-emoji="person_with_blond_hair" data-unicode-name="1F471"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F64E" title="person_with_pouting_face" data-aliases="" data-emoji="person_with_pouting_face" data-unicode-name="1F64E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F447" title="point_down" data-aliases="" data-emoji="point_down" data-unicode-name="1F447"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F448" title="point_left" data-aliases="" data-emoji="point_left" data-unicode-name="1F448"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F449" title="point_right" data-aliases="" data-emoji="point_right" data-unicode-name="1F449"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-261D" title="point_up" data-aliases="" data-emoji="point_up" data-unicode-name="261D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F446" title="point_up_2" data-aliases="" data-emoji="point_up_2" data-unicode-name="1F446"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A9" title="poop" data-aliases=":shit: :hankey: :poo:" data-emoji="poop" data-unicode-name="1F4A9"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F45D" title="pouch" data-aliases="" data-emoji="pouch" data-unicode-name="1F45D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F63E" title="pouting_cat" data-aliases="" data-emoji="pouting_cat" data-unicode-name="1F63E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F64F" title="pray" data-aliases="" data-emoji="pray" data-unicode-name="1F64F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F478" title="princess" data-aliases="" data-emoji="princess" data-unicode-name="1F478"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F44A" title="punch" data-aliases="" data-emoji="punch" data-unicode-name="1F44A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F49C" title="purple_heart" data-aliases="" data-emoji="purple_heart" data-unicode-name="1F49C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F45B" title="purse" data-aliases="" data-emoji="purse" data-unicode-name="1F45B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F621" title="rage" data-aliases="" data-emoji="rage" data-unicode-name="1F621"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-270B" title="raised_hand" data-aliases="" data-emoji="raised_hand" data-unicode-name="270B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F64C" title="raised_hands" data-aliases="" data-emoji="raised_hands" data-unicode-name="1F64C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F64B" title="raising_hand" data-aliases="" data-emoji="raising_hand" data-unicode-name="1F64B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-263A" title="relaxed" data-aliases="" data-emoji="relaxed" data-unicode-name="263A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F60C" title="relieved" data-aliases="" data-emoji="relieved" data-unicode-name="1F60C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F49E" title="revolving_hearts" data-aliases="" data-emoji="revolving_hearts" data-unicode-name="1F49E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F380" title="ribbon" data-aliases="" data-emoji="ribbon" data-unicode-name="1F380"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F48D" title="ring" data-aliases="" data-emoji="ring" data-unicode-name="1F48D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F3C3" title="runner" data-aliases="" data-emoji="runner" data-unicode-name="1F3C3"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F3BD" title="running_shirt_with_sash" data-aliases="" data-emoji="running_shirt_with_sash" data-unicode-name="1F3BD"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F461" title="sandal" data-aliases="" data-emoji="sandal" data-unicode-name="1F461"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F631" title="scream" data-aliases="" data-emoji="scream" data-unicode-name="1F631"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F640" title="scream_cat" data-aliases="" data-emoji="scream_cat" data-unicode-name="1F640"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F648" title="see_no_evil" data-aliases="" data-emoji="see_no_evil" data-unicode-name="1F648"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F455" title="shirt" data-aliases="" data-emoji="shirt" data-unicode-name="1F455"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F480" title="skull" data-aliases=":skeleton:" data-emoji="skull" data-unicode-name="1F480"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F634" title="sleeping" data-aliases="" data-emoji="sleeping" data-unicode-name="1F634"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F62A" title="sleepy" data-aliases="" data-emoji="sleepy" data-unicode-name="1F62A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F604" title="smile" data-aliases="" data-emoji="smile" data-unicode-name="1F604"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F638" title="smile_cat" data-aliases="" data-emoji="smile_cat" data-unicode-name="1F638"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F603" title="smiley" data-aliases="" data-emoji="smiley" data-unicode-name="1F603"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F63A" title="smiley_cat" data-aliases="" data-emoji="smiley_cat" data-unicode-name="1F63A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F608" title="smiling_imp" data-aliases="" data-emoji="smiling_imp" data-unicode-name="1F608"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F60F" title="smirk" data-aliases="" data-emoji="smirk" data-unicode-name="1F60F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F63C" title="smirk_cat" data-aliases="" data-emoji="smirk_cat" data-unicode-name="1F63C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F62D" title="sob" data-aliases="" data-emoji="sob" data-unicode-name="1F62D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-2728" title="sparkles" data-aliases="" data-emoji="sparkles" data-unicode-name="2728"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F496" title="sparkling_heart" data-aliases="" data-emoji="sparkling_heart" data-unicode-name="1F496"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F64A" title="speak_no_evil" data-aliases="" data-emoji="speak_no_evil" data-unicode-name="1F64A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4AC" title="speech_balloon" data-aliases="" data-emoji="speech_balloon" data-unicode-name="1F4AC"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F31F" title="star2" data-aliases="" data-emoji="star2" data-unicode-name="1F31F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F61B" title="stuck_out_tongue" data-aliases="" data-emoji="stuck_out_tongue" data-unicode-name="1F61B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F61D" title="stuck_out_tongue_closed_eyes" data-aliases="" data-emoji="stuck_out_tongue_closed_eyes" data-unicode-name="1F61D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F61C" title="stuck_out_tongue_winking_eye" data-aliases="" data-emoji="stuck_out_tongue_winking_eye" data-unicode-name="1F61C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F60E" title="sunglasses" data-aliases="" data-emoji="sunglasses" data-unicode-name="1F60E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F613" title="sweat" data-aliases="" data-emoji="sweat" data-unicode-name="1F613"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A6" title="sweat_drops" data-aliases="" data-emoji="sweat_drops" data-unicode-name="1F4A6"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F605" title="sweat_smile" data-aliases="" data-emoji="sweat_smile" data-unicode-name="1F605"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4AD" title="thought_balloon" data-aliases="" data-emoji="thought_balloon" data-unicode-name="1F4AD"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F44E" title="thumbsdown" data-aliases=":-1:" data-emoji="thumbsdown" data-unicode-name="1F44E"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F44D" title="thumbsup" data-aliases=":+1:" data-emoji="thumbsup" data-unicode-name="1F44D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F62B" title="tired_face" data-aliases="" data-emoji="tired_face" data-unicode-name="1F62B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F445" title="tongue" data-aliases="" data-emoji="tongue" data-unicode-name="1F445"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F3A9" title="tophat" data-aliases="" data-emoji="tophat" data-unicode-name="1F3A9"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F624" title="triumph" data-aliases="" data-emoji="triumph" data-unicode-name="1F624"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F495" title="two_hearts" data-aliases="" data-emoji="two_hearts" data-unicode-name="1F495"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F46C" title="two_men_holding_hands" data-aliases="" data-emoji="two_men_holding_hands" data-unicode-name="1F46C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F46D" title="two_women_holding_hands" data-aliases="" data-emoji="two_women_holding_hands" data-unicode-name="1F46D"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F612" title="unamused" data-aliases="" data-emoji="unamused" data-unicode-name="1F612"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-270C" title="v" data-aliases="" data-emoji="v" data-unicode-name="270C"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F6B6" title="walking" data-aliases="" data-emoji="walking" data-unicode-name="1F6B6"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F44B" title="wave" data-aliases="" data-emoji="wave" data-unicode-name="1F44B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F629" title="weary" data-aliases="" data-emoji="weary" data-unicode-name="1F629"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F609" title="wink" data-aliases="" data-emoji="wink" data-unicode-name="1F609"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F469" title="woman" data-aliases="" data-emoji="woman" data-unicode-name="1F469"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F45A" title="womans_clothes" data-aliases="" data-emoji="womans_clothes" data-unicode-name="1F45A"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F452" title="womans_hat" data-aliases="" data-emoji="womans_hat" data-unicode-name="1F452"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F61F" title="worried" data-aliases="" data-emoji="worried" data-unicode-name="1F61F"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F49B" title="yellow_heart" data-aliases="" data-emoji="yellow_heart" data-unicode-name="1F49B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F60B" title="yum" data-aliases="" data-emoji="yum" data-unicode-name="1F60B"></div>
</button>
</li>
<li class='pull-left text-center emoji-menu-list-item'>
<button class='emoji-menu-btn text-center js-emoji-btn' type='button'>
<div class="icon emoji-icon emoji-1F4A4" title="zzz" data-aliases="" data-emoji="zzz" data-unicode-name="1F4A4"></div>
</button>
</li>
</ul>
</div>
</div>
"""
spec/javascripts/graphs/stat_graph_contributors_util_spec.js
View file @
1311f8c2
spec/javascripts/new_branch_spec.js.coffee
View file @
1311f8c2
#= require jquery-ui
#= require jquery-ui
/autocomplete
#= require new_branch_form
describe
'Branch'
,
->
...
...
spec/lib/gitlab/badge/build_spec.rb
View file @
1311f8c2
...
...
@@ -42,8 +42,7 @@ describe Gitlab::Badge::Build do
end
context
'build exists'
do
let
(
:pipeline
)
{
create
(
:ci_pipeline
,
project:
project
,
sha:
sha
,
ref:
branch
)
}
let!
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
)
}
let!
(
:build
)
{
create_build
(
project
,
sha
,
branch
)
}
context
'build success'
do
before
{
build
.
success!
}
...
...
@@ -95,6 +94,28 @@ describe Gitlab::Badge::Build do
end
end
context
'when outdated pipeline for given ref exists'
do
before
do
build
=
create_build
(
project
,
sha
,
branch
)
build
.
success!
old_build
=
create_build
(
project
,
'11eeffdd'
,
branch
)
old_build
.
drop!
end
it
'does not take outdated pipeline into account'
do
expect
(
badge
.
to_s
).
to
eq
'build-success'
end
end
def
create_build
(
project
,
sha
,
branch
)
pipeline
=
create
(
:ci_pipeline
,
project:
project
,
sha:
sha
,
ref:
branch
)
create
(
:ci_build
,
pipeline:
pipeline
)
end
def
status_node
(
data
,
status
)
xml
=
Nokogiri
::
XML
.
parse
(
data
)
xml
.
at
(
%Q{text:contains("
#{
status
}
")}
)
...
...
spec/models/note_spec.rb
View file @
1311f8c2
...
...
@@ -9,6 +9,16 @@ describe Note, models: true do
it
{
is_expected
.
to
have_many
(
:todos
).
dependent
(
:destroy
)
}
end
describe
'modules'
do
subject
{
described_class
}
it
{
is_expected
.
to
include_module
(
Participable
)
}
it
{
is_expected
.
to
include_module
(
Mentionable
)
}
it
{
is_expected
.
to
include_module
(
Awardable
)
}
it
{
is_expected
.
to
include_module
(
Gitlab
::
CurrentSettings
)
}
end
describe
'validation'
do
it
{
is_expected
.
to
validate_presence_of
(
:note
)
}
it
{
is_expected
.
to
validate_presence_of
(
:project
)
}
...
...
vendor/assets/javascripts/task_list.js.coffee
0 → 100644
View file @
1311f8c2
# The MIT License (MIT)
#
# Copyright (c) 2014 GitHub, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# TaskList Behavior
#
#= provides tasklist:enabled
#= provides tasklist:disabled
#= provides tasklist:change
#= provides tasklist:changed
#
#
# Enables Task List update behavior.
#
# ### Example Markup
#
# <div class="js-task-list-container">
# <ul class="task-list">
# <li class="task-list-item">
# <input type="checkbox" class="js-task-list-item-checkbox" disabled />
# text
# </li>
# </ul>
# <form>
# <textarea class="js-task-list-field">- [ ] text</textarea>
# </form>
# </div>
#
# ### Specification
#
# TaskLists MUST be contained in a `(div).js-task-list-container`.
#
# TaskList Items SHOULD be an a list (`UL`/`OL`) element.
#
# Task list items MUST match `(input).task-list-item-checkbox` and MUST be
# `disabled` by default.
#
# TaskLists MUST have a `(textarea).js-task-list-field` form element whose
# `value` attribute is the source (Markdown) to be udpated. The source MUST
# follow the syntax guidelines.
#
# TaskList updates trigger `tasklist:change` events. If the change is
# successful, `tasklist:changed` is fired. The change can be canceled.
#
# jQuery is required.
#
# ### Methods
#
# `.taskList('enable')` or `.taskList()`
#
# Enables TaskList updates for the container.
#
# `.taskList('disable')`
#
# Disables TaskList updates for the container.
#
## ### Events
#
# `tasklist:enabled`
#
# Fired when the TaskList is enabled.
#
# * **Synchronicity** Sync
# * **Bubbles** Yes
# * **Cancelable** No
# * **Target** `.js-task-list-container`
#
# `tasklist:disabled`
#
# Fired when the TaskList is disabled.
#
# * **Synchronicity** Sync
# * **Bubbles** Yes
# * **Cancelable** No
# * **Target** `.js-task-list-container`
#
# `tasklist:change`
#
# Fired before the TaskList item change takes affect.
#
# * **Synchronicity** Sync
# * **Bubbles** Yes
# * **Cancelable** Yes
# * **Target** `.js-task-list-field`
#
# `tasklist:changed`
#
# Fired once the TaskList item change has taken affect.
#
# * **Synchronicity** Sync
# * **Bubbles** Yes
# * **Cancelable** No
# * **Target** `.js-task-list-field`
#
# ### NOTE
#
# Task list checkboxes are rendered as disabled by default because rendered
# user content is cached without regard for the viewer.
incomplete
=
"[ ]"
complete
=
"[x]"
# Escapes the String for regular expression matching.
escapePattern
=
(
str
)
->
str
.
replace
(
/([\[\]])/g
,
"
\\
$1"
).
# escape square brackets
replace
(
/\s/
,
"
\\
s"
).
# match all white space
replace
(
"x"
,
"[xX]"
)
# match all cases
incompletePattern
=
///
#{
escapePattern
(
incomplete
)
}
///
completePattern
=
///
#{
escapePattern
(
complete
)
}
///
# Pattern used to identify all task list items.
# Useful when you need iterate over all items.
itemPattern
=
///
^
(?:
# prefix, consisting of
\s
*
# optional leading whitespace
(?:>
\s
*)*
# zero or more blockquotes
(?:[-+*]|(?:
\d
+
\.
))
# list item indicator
)
\s
*
# optional whitespace prefix
(
# checkbox
#{
escapePattern
(
complete
)
}
|
#{
escapePattern
(
incomplete
)
}
)
\s
+
# is followed by whitespace
(?!
\(
.*?
\)
# is not part of a [foo](url) link
)
(?=
# and is followed by zero or more links
(?:
\[
.*?
\]\s
*(?:
\[
.*?
\]
|
\(
.*?
\)
)
\s
*)*
(?:[^
\[
]|$)
# and either a non-link or the end of the string
)
///
# Used to filter out code fences from the source for comparison only.
# http://rubular.com/r/x5EwZVrloI
# Modified slightly due to issues with JS
codeFencesPattern
=
///
^`{3}
# ```
(?:
\s
*
\w
+)?
# followed by optional language
[
\S\s
]
# whitespace
.*
# code
[
\S\s
]
# whitespace
^`{3}$
# ```
///mg
# Used to filter out potential mismatches (items not in lists).
# http://rubular.com/r/OInl6CiePy
itemsInParasPattern
=
///
^
(
#{
escapePattern
(
complete
)
}
|
#{
escapePattern
(
incomplete
)
}
)
.+
$
///g
# Given the source text, updates the appropriate task list item to match the
# given checked value.
#
# Returns the updated String text.
updateTaskListItem
=
(
source
,
itemIndex
,
checked
)
->
clean
=
source
.
replace
(
/\r/g
,
''
).
replace
(
codeFencesPattern
,
''
).
replace
(
itemsInParasPattern
,
''
).
split
(
"
\n
"
)
index
=
0
result
=
for
line
in
source
.
split
(
"
\n
"
)
if
line
in
clean
&&
line
.
match
(
itemPattern
)
index
+=
1
if
index
==
itemIndex
line
=
if
checked
line
.
replace
(
incompletePattern
,
complete
)
else
line
.
replace
(
completePattern
,
incomplete
)
line
result
.
join
(
"
\n
"
)
# Updates the $field value to reflect the state of $item.
# Triggers the `tasklist:change` event before the value has changed, and fires
# a `tasklist:changed` event once the value has changed.
updateTaskList
=
(
$item
)
->
$container
=
$item
.
closest
'.js-task-list-container'
$field
=
$container
.
find
'.js-task-list-field'
index
=
1
+
$container
.
find
(
'.task-list-item-checkbox'
).
index
(
$item
)
checked
=
$item
.
prop
'checked'
event
=
$
.
Event
'tasklist:change'
$field
.
trigger
event
,
[
index
,
checked
]
unless
event
.
isDefaultPrevented
()
$field
.
val
updateTaskListItem
(
$field
.
val
(),
index
,
checked
)
$field
.
trigger
'change'
$field
.
trigger
'tasklist:changed'
,
[
index
,
checked
]
# When the task list item checkbox is updated, submit the change
$
(
document
).
on
'change'
,
'.task-list-item-checkbox'
,
->
updateTaskList
$
(
this
)
# Enables TaskList item changes.
enableTaskList
=
(
$container
)
->
if
$container
.
find
(
'.js-task-list-field'
).
length
>
0
$container
.
find
(
'.task-list-item'
).
addClass
(
'enabled'
).
find
(
'.task-list-item-checkbox'
).
attr
(
'disabled'
,
null
)
$container
.
addClass
(
'is-task-list-enabled'
).
trigger
'tasklist:enabled'
# Enables a collection of TaskList containers.
enableTaskLists
=
(
$containers
)
->
for
container
in
$containers
enableTaskList
$
(
container
)
# Disable TaskList item changes.
disableTaskList
=
(
$container
)
->
$container
.
find
(
'.task-list-item'
).
removeClass
(
'enabled'
).
find
(
'.task-list-item-checkbox'
).
attr
(
'disabled'
,
'disabled'
)
$container
.
removeClass
(
'is-task-list-enabled'
).
trigger
'tasklist:disabled'
# Disables a collection of TaskList containers.
disableTaskLists
=
(
$containers
)
->
for
container
in
$containers
disableTaskList
$
(
container
)
$
.
fn
.
taskList
=
(
method
)
->
$container
=
$
(
this
).
closest
(
'.js-task-list-container'
)
methods
=
enable
:
enableTaskLists
disable
:
disableTaskLists
methods
[
method
||
'enable'
](
$container
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment