Commit 7a519bc1 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' into new-buttons

parents f30f518f 2803b6e8
......@@ -190,7 +190,7 @@ gem 'mousetrap-rails', '~> 1.4.6'
# Detect and convert string character encoding
gem 'charlock_holmes', '~> 0.7.3'
gem "sass-rails", '~> 4.0.5'
gem "sass-rails", '~> 5.0.0'
gem "coffee-rails", '~> 4.1.0'
gem "uglifier", '~> 2.7.2'
gem 'turbolinks', '~> 2.5.0'
......
......@@ -647,12 +647,13 @@ GEM
safe_yaml (1.0.4)
sanitize (2.1.0)
nokogiri (>= 1.4.4)
sass (3.2.19)
sass-rails (4.0.5)
sass (3.4.20)
sass-rails (5.0.4)
railties (>= 4.0.0, < 5.0)
sass (~> 3.2.2)
sprockets (~> 2.8, < 3.0)
sprockets-rails (~> 2.0)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sawyer (0.6.0)
addressable (~> 2.3.5)
faraday (~> 0.8, < 0.10)
......@@ -934,7 +935,7 @@ DEPENDENCIES
rubocop (~> 0.35.0)
ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0)
sass-rails (~> 4.0.5)
sass-rails (~> 5.0.0)
sdoc (~> 0.3.20)
seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9)
......
class @AwardsHandler
constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
$(".add-award").click (event)->
event.stopPropagation()
event.preventDefault()
$(".emoji-menu").show()
$("html").click ->
if !$(event.target).closest(".emoji-menu").length
if $(".emoji-menu").is(":visible")
$(".emoji-menu").hide()
addAward: (emoji) ->
emoji = @normilizeEmojiName(emoji)
@postEmoji emoji, =>
@addAwardToEmojiBar(emoji)
addAwardToEmojiBar: (emoji, custom_path = '') ->
$(".emoji-menu").hide()
addAwardToEmojiBar: (emoji) ->
emoji = @normilizeEmojiName(emoji)
if @exist(emoji)
if @isActive(emoji)
......@@ -17,7 +28,7 @@ class @AwardsHandler
counter.parent().addClass("active")
@addMeToAuthorList(emoji)
else
@createEmoji(emoji, custom_path)
@createEmoji(emoji)
exist: (emoji) ->
@findEmojiIcon(emoji).length > 0
......@@ -54,31 +65,29 @@ class @AwardsHandler
resetTooltip: (award) ->
award.tooltip("destroy")
# "destroy" call is asynchronous, this is why we need to set timeout.
# "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
setTimeout (->
award.tooltip()
), 200
createEmoji: (emoji, custom_path) ->
createEmoji: (emoji) ->
emojiCssClass = @resolveNameToCssClass(emoji)
nodes = []
nodes.push("<div class='award active' title='me'>")
nodes.push("<div class='icon' data-emoji='" + emoji + "'>")
nodes.push(@getImage(emoji, custom_path))
nodes.push("<div class='icon emoji-icon " + emojiCssClass + "' data-emoji='" + emoji + "'></div>")
nodes.push("<div class='counter'>1</div>")
nodes.push("</div>")
nodes.push("<div class='counter'>1")
nodes.push("</div></div>")
$(".awards-controls").before(nodes.join("\n"))
emoji_node = $(nodes.join("\n")).insertBefore(".awards-controls").find(".emoji-icon").data("emoji", emoji)
$(".award").tooltip()
getImage: (emoji, custom_path) ->
if custom_path
$("<img>").attr({src: custom_path, width: 20, height: 20}).wrap("<div>").parent().html()
else
$("li[data-emoji='" + emoji + "']").html()
resolveNameToCssClass: (emoji) ->
unicodeName = $(".emoji-menu-content [data-emoji='?']".replace("?", emoji)).data("unicode-name")
"emoji-" + unicodeName
postEmoji: (emoji, callback) ->
$.post @post_emoji_url, { note: {
......@@ -90,7 +99,7 @@ class @AwardsHandler
callback.call()
findEmojiIcon: (emoji) ->
$(".icon[data-emoji='" + emoji + "']")
$(".award [data-emoji='" + emoji + "']")
scrollToAwards: ->
$('body, html').animate({
......
......@@ -127,7 +127,7 @@ class @Notes
@initTaskList()
if note.award
awards_handler.addAwardToEmojiBar(note.note, note.emoji_path)
awards_handler.addAwardToEmojiBar(note.note)
awards_handler.scrollToAwards()
###
......
......@@ -2,6 +2,12 @@
@include clearfix;
line-height: 34px;
.emoji-icon {
width: 20px;
height: 20px;
margin: 7px 0 0 5px;
}
.award {
@include border-radius(5px);
......@@ -40,6 +46,7 @@
}
.awards-controls {
position: relative;
margin-left: 10px;
float: left;
......@@ -55,32 +62,60 @@
}
}
.awards-menu {
.emoji-menu{
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
font-size: 14px;
text-align: left;
list-style: none;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #ccc;
border: 1px solid rgba(0,0,0,.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175);
box-shadow: 0 6px 12px rgba(0,0,0,.175);
.emoji-menu-content {
padding: $gl-padding;
min-width: 214px;
width: 300px;
height: 300px;
overflow-y: scroll;
> li {
h5 {
clear: left;
}
ul {
list-style-type: none;
margin-left: -20px;
margin-bottom: 20px;
overflow: auto;
}
li {
cursor: pointer;
width: 30px;
height: 30px;
text-align: center;
float: left;
margin: 3px;
list-decorate: none;
@include border-radius(5px);
img {
margin-bottom: 2px;
}
&:hover {
background-color: #ccc;
}
}
}
}
.awards-menu{
li {
float: left;
margin: 3px;
}
}
}
This diff is collapsed.
......@@ -19,8 +19,10 @@ module Ci
@error = e.message
@status = false
rescue
@error = "Undefined error"
@error = 'Undefined error'
@status = false
ensure
render :show
end
end
end
......@@ -139,7 +139,6 @@ class Projects::NotesController < Projects::ApplicationController
discussion_id: note.discussion_id,
html: note_to_html(note),
award: note.is_award,
emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "",
note: note.note,
discussion_html: note_to_discussion_html(note),
discussion_with_diff_html: note_to_discussion_with_diff_html(note)
......
......@@ -94,11 +94,13 @@ module IssuesHelper
end.sort.to_sentence(last_word_connector: ', or ')
end
def url_to_emoji(name)
emoji_path = ::AwardEmoji.path_to_emoji_image(name)
url_to_image(emoji_path)
rescue StandardError
""
def emoji_icon(name, unicode = nil)
unicode ||= Emoji.emoji_filename(name)
content_tag :div, "",
class: "icon emoji-icon emoji-#{unicode}",
"data-emoji" => name,
"data-unicode-name" => unicode
end
def emoji_author_list(notes, current_user)
......@@ -109,10 +111,6 @@ module IssuesHelper
list.join(", ")
end
def emoji_list
::AwardEmoji::EMOJI_LIST
end
def note_active_class(notes, current_user)
if current_user && notes.pluck(:author_id).include?(current_user.id)
"active"
......
......@@ -41,5 +41,3 @@
%i.fa.fa-remove.incorrect-syntax
%b Error:
= @error
:plain
$(".results").html("#{escape_javascript(render "create")}")
\ No newline at end of file
%h2 Check your .gitlab-ci.yml
%hr
= form_tag ci_lint_path, method: :post, remote: true do
.control-group
= label_tag :content, "Content of .gitlab-ci.yml", class: 'control-label'
.controls
.row
= form_tag ci_lint_path, method: :post do
.form-group
= label_tag :content, 'Content of .gitlab-ci.yml', class: 'control-label text-nowrap'
.col-sm-12
= text_area_tag :content, nil, class: 'form-control span1', rows: 7, require: true
.col-sm-12
.pull-left.prepend-top-10
= submit_tag 'Validate', class: 'btn btn-success submit-yml'
.control-group.clearfix
.controls.pull-left.prepend-top-10
= submit_tag "Validate", class: 'btn btn-success submit-yml'
%p.text-center.loading
%i.fa.fa-refresh.fa-spin
.results.prepend-top-20
:javascript
$(".loading").hide();
$('form').bind('ajax:beforeSend', function() {
$(".loading").show();
});
$('form').bind('ajax:complete', function() {
$(".loading").hide();
});
.row.prepend-top-20
.col-sm-12
.results
= render partial: 'create' if defined?(@status)
.awards.votes-block
- votable.notes.awards.grouped_awards.each do |emoji, notes|
.award{class: (note_active_class(notes, current_user)), title: emoji_author_list(notes, current_user)}
.icon{"data-emoji" => "#{emoji}"}
= image_tag url_to_emoji(emoji), height: "20px", width: "20px"
= emoji_icon(emoji)
.counter
= notes.count
- if current_user
.dropdown.awards-controls
.awards-controls
%a.add-award{"data-toggle" => "dropdown", "data-target" => "#", "href" => "#"}
= icon('smile-o')
%ul.dropdown-menu.awards-menu
- emoji_list.each do |emoji|
%li{"data-emoji" => "#{emoji}"}= image_tag url_to_emoji(emoji), height: "20px", width: "20px"
.emoji-menu
.emoji-menu-content
- AwardEmoji.emoji_by_category.each do |category, emojis|
%h5= AwardEmoji::CATEGORIES[category]
%ul
- emojis.each do |emoji|
%li
= emoji_icon(emoji["name"], emoji["unicode"])
- if current_user
:coffeescript
......@@ -20,10 +24,16 @@
noteable_type = "#{votable.class.name.underscore}"
noteable_id = "#{votable.id}"
aliases = #{AwardEmoji::ALIASES.to_json}
window.awards_handler = new AwardsHandler(post_emoji_url, noteable_type, noteable_id, aliases)
$(".awards-menu li").click (e)->
emoji = $(this).data("emoji")
window.awards_handler = new AwardsHandler(
post_emoji_url,
noteable_type,
noteable_id,
aliases
)
$(".emoji-menu-content li").click (e)->
emoji = $(this).find(".emoji-icon").data("emoji")
awards_handler.addAward(emoji)
$(".awards").on "click", ".award", (e)->
......@@ -31,3 +41,5 @@
awards_handler.addAward(emoji)
$(".award").tooltip()
$(".emoji-menu-content").niceScroll({cursorwidth: "7px", autohidemode: false})
......@@ -13,6 +13,11 @@ Feature: Award Emoji
Then I have award added
And I can remove it by clicking to icon
@javascript
Scenario: I can see the list of emoji categories
Given I click to emoji-picker
Then I can see the activity and food categories
@javascript
Scenario: I add award emoji using regular comment
Given I leave comment with a single emoji
......
......@@ -15,8 +15,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
end
step 'I click to emoji in the picker' do
page.within '.awards-menu' do
page.first('img').click
page.within '.emoji-menu' do
page.first('.emoji-icon').click
end
end
......@@ -27,6 +27,13 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
end
end
step 'I can see the activity and food categories' do
page.within '.emoji-menu' do
expect(page).to_not have_selector 'Activity'
expect(page).to_not have_selector 'Food'
end
end
step 'I have award added' do
page.within '.awards' do
expect(page).to have_selector '.award'
......
class AwardEmoji
EMOJI_LIST = [
"+1", "-1", "100", "blush", "heart", "smile", "rage",
"beers", "disappointed", "ok_hand",
"helicopter", "shit", "airplane", "alarm_clock",
"ambulance", "anguished", "two_hearts", "wink"
]
ALIASES = {
pout: "rage",
satisfied: "laughing",
......@@ -37,11 +30,41 @@ class AwardEmoji
squirrel: "shipit"
}.with_indifferent_access
def self.path_to_emoji_image(name)
"emoji/#{Emoji.emoji_filename(name)}.png"
end
CATEGORIES = {
other: "Other",
objects: "Objects",
places: "Places",
travel_places: "Travel",
emoticons: "Emoticons",
objects_symbols: "Symbols",
nature: "Nature",
celebration: "Celebration",
people: "People",
activity: "Activity",
flags: "Flags",
food_drink: "Food"
}.with_indifferent_access
def self.normilize_emoji_name(name)
ALIASES[name] || name
end
def self.emoji_by_category
unless @emoji_by_category
@emoji_by_category = {}
emojis_added = []
Emoji.emojis.each do |emoji_name, data|
next if emojis_added.include?(data["name"])
emojis_added << data["name"]
@emoji_by_category[data["category"]] ||= []
@emoji_by_category[data["category"]] << data
end
@emoji_by_category = @emoji_by_category.sort.to_h
end
@emoji_by_category
end
end
require 'spec_helper'
describe 'CI Lint' do
before do
login_as :user
end
describe 'YAML parsing' do
before do
visit ci_lint_path
fill_in 'content', with: yaml_content
click_on 'Validate'
end
context 'YAML is correct' do
let(:yaml_content) do
File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
end
it 'Yaml parsing' do
within "table" do
expect(page).to have_content('Job - rspec')
expect(page).to have_content('Job - spinach')
expect(page).to have_content('Deploy Job - staging')
expect(page).to have_content('Deploy Job - production')
end
end
end
context 'YAML is incorrect' do
let(:yaml_content) { '' }
it 'displays information about an error' do
expect(page).to have_content('Status: syntax is incorrect')
expect(page).to have_content('Error: Please provide content of .gitlab-ci.yml')
end
end
end
end
require 'spec_helper'
describe "Lint" do
before do
login_as :user
end
it "Yaml parsing", js: true do
content = File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
visit ci_lint_path
fill_in "content", with: content
click_on "Validate"
within "table" do
expect(page).to have_content("Job - rspec")
expect(page).to have_content("Job - spinach")
expect(page).to have_content("Deploy Job - staging")
expect(page).to have_content("Deploy Job - production")
end
end
it "Yaml parsing with error", js: true do
visit ci_lint_path
fill_in "content", with: ""
click_on "Validate"
expect(page).to have_content("Status: syntax is incorrect")
expect(page).to have_content("Error: Please provide content of .gitlab-ci.yml")
end
end
......@@ -127,18 +127,6 @@ describe IssuesHelper do
it { is_expected.to eq("!1, !2, or !3") }
end
describe "#url_to_emoji" do
it "returns url" do
expect(url_to_emoji("smile")).to include("emoji/1F604.png")
end
end
describe "#emoji_list" do
it "returns url" do
expect(emoji_list).to be_kind_of(Array)
end
end
describe "#note_active_class" do
before do
@note = create :note
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment