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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
a695b855
Commit
a695b855
authored
Apr 17, 2017
by
Luke "Jared" Bennett
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into droplab-templating-xss-fix
parents
9fe127ff
970f9624
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
149 additions
and
60 deletions
+149
-60
app/assets/javascripts/awards_handler.js
app/assets/javascripts/awards_handler.js
+36
-17
app/assets/javascripts/diff_notes/components/resolve_btn.js
app/assets/javascripts/diff_notes/components/resolve_btn.js
+4
-4
app/assets/javascripts/issue_show/index.js
app/assets/javascripts/issue_show/index.js
+15
-21
app/assets/javascripts/issue_show/issue_title.vue
app/assets/javascripts/issue_show/issue_title.vue
+6
-3
app/views/projects/issues/show.html.haml
app/views/projects/issues/show.html.haml
+1
-0
changelogs/unreleased/27655-clear-emoji-search-after-selection.yml
...s/unreleased/27655-clear-emoji-search-after-selection.yml
+4
-0
changelogs/unreleased/fix-trace-encoding.yml
changelogs/unreleased/fix-trace-encoding.yml
+4
-0
config/webpack.config.js
config/webpack.config.js
+1
-0
features/steps/project/issues/award_emoji.rb
features/steps/project/issues/award_emoji.rb
+3
-3
lib/banzai/reference_parser/base_parser.rb
lib/banzai/reference_parser/base_parser.rb
+2
-1
lib/gitlab/ci/trace/stream.rb
lib/gitlab/ci/trace/stream.rb
+9
-2
spec/javascripts/awards_handler_spec.js
spec/javascripts/awards_handler_spec.js
+24
-4
spec/javascripts/issue_show/issue_title_spec.js
spec/javascripts/issue_show/issue_title_spec.js
+1
-1
spec/lib/banzai/reference_parser/base_parser_spec.rb
spec/lib/banzai/reference_parser/base_parser_spec.rb
+21
-2
spec/lib/gitlab/ci/trace/stream_spec.rb
spec/lib/gitlab/ci/trace/stream_spec.rb
+18
-2
No files found.
app/assets/javascripts/awards_handler.js
View file @
a695b855
...
...
@@ -8,6 +8,7 @@ import { glEmojiTag } from './behaviors/gl_emoji';
import
isEmojiNameValid
from
'
./behaviors/gl_emoji/is_emoji_name_valid
'
;
const
animationEndEventString
=
'
animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd
'
;
const
transitionEndEventString
=
'
transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd
'
;
const
requestAnimationFrame
=
window
.
requestAnimationFrame
||
window
.
webkitRequestAnimationFrame
||
window
.
mozRequestAnimationFrame
||
...
...
@@ -105,8 +106,9 @@ function AwardsHandler() {
const
$glEmojiElement
=
$target
.
find
(
'
gl-emoji
'
);
const
$spriteIconElement
=
$target
.
find
(
'
.icon
'
);
const
emoji
=
(
$glEmojiElement
.
length
?
$glEmojiElement
:
$spriteIconElement
).
data
(
'
name
'
);
$target
.
closest
(
'
.js-awards-block
'
).
addClass
(
'
current
'
);
return
this
.
addAward
(
this
.
getVotesBlock
(),
this
.
getAwardUrl
(),
emoji
);
this
.
addAward
(
this
.
getVotesBlock
(),
this
.
getAwardUrl
(),
emoji
);
});
}
...
...
@@ -132,12 +134,12 @@ AwardsHandler.prototype.showEmojiMenu = function showEmojiMenu($addBtn) {
if
(
$menu
.
is
(
'
.is-visible
'
))
{
$addBtn
.
removeClass
(
'
is-active
'
);
$menu
.
removeClass
(
'
is-visible
'
);
$
(
'
#emoji_
search
'
).
blur
();
$
(
'
.js-emoji-menu-
search
'
).
blur
();
}
else
{
$addBtn
.
addClass
(
'
is-active
'
);
this
.
positionMenu
(
$menu
,
$addBtn
);
$menu
.
addClass
(
'
is-visible
'
);
$
(
'
#emoji_
search
'
).
focus
();
$
(
'
.js-emoji-menu-
search
'
).
focus
();
}
}
else
{
$addBtn
.
addClass
(
'
is-loading is-active
'
);
...
...
@@ -147,7 +149,7 @@ AwardsHandler.prototype.showEmojiMenu = function showEmojiMenu($addBtn) {
this
.
positionMenu
(
$createdMenu
,
$addBtn
);
return
setTimeout
(()
=>
{
$createdMenu
.
addClass
(
'
is-visible
'
);
$
(
'
#emoji_
search
'
).
focus
();
$
(
'
.js-emoji-menu-
search
'
).
focus
();
},
200
);
});
}
...
...
@@ -180,7 +182,7 @@ AwardsHandler.prototype.createEmojiMenu = function createEmojiMenu(callback) {
const
emojiMenuMarkup
=
`
<div class="emoji-menu">
<input type="text" name="emoji
_search" id="emoji_search" value="" class="
emoji-search search-input form-control" placeholder="Search emoji" />
<input type="text" name="emoji
-menu-search" value="" class="js-emoji-menu-search
emoji-search search-input form-control" placeholder="Search emoji" />
<div class="emoji-menu-content">
${
frequentlyUsedCatgegory
}
...
...
@@ -500,24 +502,41 @@ AwardsHandler.prototype.getFrequentlyUsedEmojis = function getFrequentlyUsedEmoj
};
AwardsHandler
.
prototype
.
setupSearch
=
function
setupSearch
()
{
this
.
registerEventListener
(
'
on
'
,
$
(
'
input.emoji-search
'
),
'
input
'
,
(
e
)
=>
{
const
$search
=
$
(
'
.js-emoji-menu-search
'
);
this
.
registerEventListener
(
'
on
'
,
$search
,
'
input
'
,
(
e
)
=>
{
const
term
=
$
(
e
.
target
).
val
().
trim
();
// Clean previous search results
$
(
'
ul.emoji-menu-search, h5.emoji-search-title
'
).
remove
();
if
(
term
.
length
>
0
)
{
// Generate a search result block
const
h5
=
$
(
'
<h5 class="emoji-search-title"/>
'
).
text
(
'
Search results
'
);
const
foundEmojis
=
this
.
searchEmojis
(
term
).
show
();
const
ul
=
$
(
'
<ul>
'
).
addClass
(
'
emoji-menu-list emoji-menu-search
'
).
append
(
foundEmojis
);
$
(
'
.emoji-menu-content ul, .emoji-menu-content h5
'
).
hide
();
$
(
'
.emoji-menu-content
'
).
append
(
h5
).
append
(
ul
);
}
else
{
$
(
'
.emoji-menu-content
'
).
children
().
show
();
this
.
searchEmojis
(
term
);
});
const
$menu
=
$
(
'
.emoji-menu
'
);
this
.
registerEventListener
(
'
on
'
,
$menu
,
transitionEndEventString
,
(
e
)
=>
{
if
(
e
.
target
===
e
.
currentTarget
)
{
// Clear the search
this
.
searchEmojis
(
''
);
}
});
};
AwardsHandler
.
prototype
.
searchEmojis
=
function
searchEmojis
(
term
)
{
const
$search
=
$
(
'
.js-emoji-menu-search
'
);
$search
.
val
(
term
);
// Clean previous search results
$
(
'
ul.emoji-menu-search, h5.emoji-search-title
'
).
remove
();
if
(
term
.
length
>
0
)
{
// Generate a search result block
const
h5
=
$
(
'
<h5 class="emoji-search-title"/>
'
).
text
(
'
Search results
'
);
const
foundEmojis
=
this
.
findMatchingEmojiElements
(
term
).
show
();
const
ul
=
$
(
'
<ul>
'
).
addClass
(
'
emoji-menu-list emoji-menu-search
'
).
append
(
foundEmojis
);
$
(
'
.emoji-menu-content ul, .emoji-menu-content h5
'
).
hide
();
$
(
'
.emoji-menu-content
'
).
append
(
h5
).
append
(
ul
);
}
else
{
$
(
'
.emoji-menu-content
'
).
children
().
show
();
}
};
AwardsHandler
.
prototype
.
findMatchingEmojiElements
=
function
findMatchingEmojiElements
(
term
)
{
const
safeTerm
=
term
.
toLowerCase
();
const
namesMatchingAlias
=
[];
...
...
app/assets/javascripts/diff_notes/components/resolve_btn.js
View file @
a695b855
...
...
@@ -20,8 +20,7 @@ import Vue from 'vue';
data
:
function
()
{
return
{
discussions
:
CommentsStore
.
state
,
loading
:
false
,
note
:
{},
loading
:
false
};
},
watch
:
{
...
...
@@ -34,6 +33,9 @@ import Vue from 'vue';
discussion
:
function
()
{
return
this
.
discussions
[
this
.
discussionId
];
},
note
:
function
()
{
return
this
.
discussion
?
this
.
discussion
.
getNote
(
this
.
noteId
)
:
{};
},
buttonText
:
function
()
{
if
(
this
.
isResolved
)
{
return
`Resolved by
${
this
.
resolvedByName
}
`
;
...
...
@@ -112,8 +114,6 @@ import Vue from 'vue';
authorAvatar
:
this
.
authorAvatar
,
noteTruncated
:
this
.
noteTruncated
,
});
this
.
note
=
this
.
discussion
.
getNote
(
this
.
noteId
);
}
});
...
...
app/assets/javascripts/issue_show/index.js
View file @
a695b855
import
Vue
from
'
vue
'
;
import
IssueTitle
from
'
./issue_title
'
;
import
IssueTitle
from
'
./issue_title
.vue
'
;
import
'
../vue_shared/vue_resource_interceptor
'
;
const
vueOptions
=
()
=>
({
el
:
'
.issue-title-entrypoint
'
,
components
:
{
IssueTitle
,
},
data
()
{
const
issueTitleData
=
document
.
querySelector
(
'
.issue-title-data
'
).
dataset
;
(()
=>
{
const
issueTitleData
=
document
.
querySelector
(
'
.issue-title-data
'
).
dataset
;
const
{
initialTitle
,
endpoint
}
=
issueTitleData
;
return
{
initialTitle
:
issueTitleData
.
initialTitle
,
endpoint
:
issueTitleData
.
endpoint
,
};
},
template
:
`
<IssueTitle
:initialTitle="initialTitle"
:endpoint="endpoint"
/>
`
,
});
const
vm
=
new
Vue
({
el
:
'
.issue-title-entrypoint
'
,
render
:
createElement
=>
createElement
(
IssueTitle
,
{
props
:
{
initialTitle
,
endpoint
,
},
}),
});
(()
=>
new
Vue
(
vueOptions
()))();
return
vm
;
})();
app/assets/javascripts/issue_show/issue_title.
js
→
app/assets/javascripts/issue_show/issue_title.
vue
View file @
a695b855
<
script
>
import
Visibility
from
'
visibilityjs
'
;
import
Poll
from
'
./../lib/utils/poll
'
;
import
Service
from
'
./services/index
'
;
...
...
@@ -72,7 +73,9 @@ export default {
created
()
{
this
.
fetch
();
},
template
:
`
<h2 class='title' v-html='title'></h2>
`
,
};
</
script
>
<
template
>
<h2
class=
"title"
v-html=
"title"
></h2>
</
template
>
app/views/projects/issues/show.html.haml
View file @
a695b855
...
...
@@ -79,4 +79,5 @@
=
render
'shared/issuable/sidebar'
,
issuable:
@issue
=
page_specific_javascript_bundle_tag
(
'common_vue'
)
=
page_specific_javascript_bundle_tag
(
'issue_show'
)
changelogs/unreleased/27655-clear-emoji-search-after-selection.yml
0 → 100644
View file @
a695b855
---
title
:
Clear emoji search in awards menu after picking emoji
merge_request
:
author
:
changelogs/unreleased/fix-trace-encoding.yml
0 → 100644
View file @
a695b855
---
title
:
Fix another case where trace does not have proper encoding set
merge_request
:
10728
author
:
config/webpack.config.js
View file @
a695b855
...
...
@@ -125,6 +125,7 @@ var config = {
'
notebook_viewer
'
,
'
pdf_viewer
'
,
'
vue_pipelines
'
,
'
issue_show
'
,
],
minChunks
:
function
(
module
,
count
)
{
return
module
.
resource
&&
(
/vue_shared/
).
test
(
module
.
resource
);
...
...
features/steps/project/issues/award_emoji.rb
View file @
a695b855
...
...
@@ -87,7 +87,7 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
end
step
'I search "hand"'
do
fill_in
'emoji
_
search'
,
with:
'hand'
fill_in
'emoji
-menu-
search'
,
with:
'hand'
end
step
'I see search result for "hand"'
do
...
...
@@ -101,7 +101,7 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
end
step
'The search field is focused'
do
expect
(
page
).
to
have_selector
(
'
#emoji_
search'
)
expect
(
page
.
evaluate_script
(
'document.activeElement.id'
)).
to
eq
(
'emoji_search'
)
expect
(
page
).
to
have_selector
(
'
.js-emoji-menu-
search'
)
expect
(
page
.
evaluate_script
(
"document.activeElement.classList.contains('js-emoji-menu-search')"
)).
to
eq
(
true
)
end
end
lib/banzai/reference_parser/base_parser.rb
View file @
a695b855
...
...
@@ -136,7 +136,8 @@ module Banzai
nodes
.
each_with_object
({})
do
|
node
,
hash
|
if
node
.
has_attribute?
(
attribute
)
hash
[
node
]
=
objects_by_id
[
node
.
attr
(
attribute
).
to_i
]
obj
=
objects_by_id
[
node
.
attr
(
attribute
).
to_i
]
hash
[
node
]
=
obj
if
obj
end
end
end
...
...
lib/gitlab/ci/trace/stream.rb
View file @
a695b855
...
...
@@ -14,6 +14,14 @@ module Gitlab
def
initialize
@stream
=
yield
if
@stream
@stream
.
binmode
# Ci::Ansi2html::Converter would read from @stream directly,
# using @stream.each_line to be specific. It's safe to set
# the encoding here because IO#seek(bytes) and IO#read(bytes)
# are not characters based, so encoding doesn't matter to them.
@stream
.
set_encoding
(
Encoding
.
default_external
)
end
end
def
valid?
...
...
@@ -51,7 +59,7 @@ module Gitlab
read_last_lines
(
last_lines
)
else
stream
.
read
end
end
.
force_encoding
(
Encoding
.
default_external
)
end
def
html_with_state
(
state
=
nil
)
...
...
@@ -113,7 +121,6 @@ module Gitlab
end
chunks
.
join
.
lines
.
last
(
last_lines
).
join
.
force_encoding
(
Encoding
.
default_external
)
end
end
end
...
...
spec/javascripts/awards_handler_spec.js
View file @
a695b855
...
...
@@ -65,7 +65,7 @@ require('~/lib/utils/common_utils');
$emojiMenu
=
$
(
'
.emoji-menu
'
);
expect
(
$emojiMenu
.
length
).
toBe
(
1
);
expect
(
$emojiMenu
.
hasClass
(
'
is-visible
'
)).
toBe
(
true
);
expect
(
$emojiMenu
.
find
(
'
#emoji_
search
'
).
length
).
toBe
(
1
);
expect
(
$emojiMenu
.
find
(
'
.js-emoji-menu-
search
'
).
length
).
toBe
(
1
);
return
expect
(
$
(
'
.js-awards-block.current
'
).
length
).
toBe
(
1
);
});
});
...
...
@@ -217,16 +217,35 @@ require('~/lib/utils/common_utils');
return
expect
(
$thumbsUpEmoji
.
data
(
"
original-title
"
)).
toBe
(
'
sam
'
);
});
});
describe
(
'
search
'
,
function
()
{
return
it
(
'
should filter the emoji
'
,
function
(
done
)
{
describe
(
'
::searchEmojis
'
,
()
=>
{
it
(
'
should filter the emoji
'
,
function
(
done
)
{
return
openAndWaitForEmojiMenu
()
.
then
(()
=>
{
expect
(
$
(
'
[data-name=angel]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
expect
(
$
(
'
[data-name=anger]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
$
(
'
#emoji_search
'
).
val
(
'
ali
'
).
trigger
(
'
input
'
);
awardsHandler
.
searchEmojis
(
'
ali
'
);
expect
(
$
(
'
[data-name=angel]
'
).
is
(
'
:visible
'
)).
toBe
(
false
);
expect
(
$
(
'
[data-name=anger]
'
).
is
(
'
:visible
'
)).
toBe
(
false
);
expect
(
$
(
'
[data-name=alien]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
expect
(
$
(
'
.js-emoji-menu-search
'
).
val
()).
toBe
(
'
ali
'
);
})
.
then
(
done
)
.
catch
((
err
)
=>
{
done
.
fail
(
`Failed to open and build emoji menu:
${
err
.
message
}
`
);
});
});
it
(
'
should clear the search when searching for nothing
'
,
function
(
done
)
{
return
openAndWaitForEmojiMenu
()
.
then
(()
=>
{
awardsHandler
.
searchEmojis
(
'
ali
'
);
expect
(
$
(
'
[data-name=angel]
'
).
is
(
'
:visible
'
)).
toBe
(
false
);
expect
(
$
(
'
[data-name=anger]
'
).
is
(
'
:visible
'
)).
toBe
(
false
);
expect
(
$
(
'
[data-name=alien]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
awardsHandler
.
searchEmojis
(
''
);
expect
(
$
(
'
[data-name=angel]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
expect
(
$
(
'
[data-name=anger]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
expect
(
$
(
'
[data-name=alien]
'
).
is
(
'
:visible
'
)).
toBe
(
true
);
expect
(
$
(
'
.js-emoji-menu-search
'
).
val
()).
toBe
(
''
);
})
.
then
(
done
)
.
catch
((
err
)
=>
{
...
...
@@ -234,6 +253,7 @@ require('~/lib/utils/common_utils');
});
});
});
describe
(
'
emoji menu
'
,
function
()
{
const
emojiSelector
=
'
[data-name="sunglasses"]
'
;
const
openEmojiMenuAndAddEmoji
=
function
()
{
...
...
spec/javascripts/issue_show/issue_title_spec.js
View file @
a695b855
import
Vue
from
'
vue
'
;
import
issueTitle
from
'
~/issue_show/issue_title
'
;
import
issueTitle
from
'
~/issue_show/issue_title
.vue
'
;
describe
(
'
Issue Title
'
,
()
=>
{
let
IssueTitleComponent
;
...
...
spec/lib/banzai/reference_parser/base_parser_spec.rb
View file @
a695b855
...
...
@@ -114,8 +114,27 @@ describe Banzai::ReferenceParser::BaseParser, lib: true do
expect
(
hash
).
to
eq
({
link
=>
user
})
end
it
'returns an empty Hash when the list of nodes is empty'
do
expect
(
subject
.
grouped_objects_for_nodes
([],
User
,
'data-user'
)).
to
eq
({})
it
'returns an empty Hash when entry does not exist in the database'
do
link
=
double
(
:link
)
expect
(
link
).
to
receive
(
:has_attribute?
).
with
(
'data-user'
).
and_return
(
true
)
expect
(
link
).
to
receive
(
:attr
).
with
(
'data-user'
).
and_return
(
'1'
)
nodes
=
[
link
]
bad_id
=
user
.
id
+
100
expect
(
subject
).
to
receive
(
:unique_attribute_values
).
with
(
nodes
,
'data-user'
).
and_return
([
bad_id
.
to_s
])
hash
=
subject
.
grouped_objects_for_nodes
(
nodes
,
User
,
'data-user'
)
expect
(
hash
).
to
eq
({})
end
end
...
...
spec/lib/gitlab/ci/trace/stream_spec.rb
View file @
a695b855
...
...
@@ -43,13 +43,29 @@ describe Gitlab::Ci::Trace::Stream do
it
'forwards to the next linefeed, case 1'
do
stream
.
limit
(
7
)
expect
(
stream
.
raw
).
to
eq
(
''
)
result
=
stream
.
raw
expect
(
result
).
to
eq
(
''
)
expect
(
result
.
encoding
).
to
eq
(
Encoding
.
default_external
)
end
it
'forwards to the next linefeed, case 2'
do
stream
.
limit
(
29
)
expect
(
stream
.
raw
).
to
eq
(
"
\e
[01;32m許功蓋
\e
[0m
\n
"
)
result
=
stream
.
raw
expect
(
result
).
to
eq
(
"
\e
[01;32m許功蓋
\e
[0m
\n
"
)
expect
(
result
.
encoding
).
to
eq
(
Encoding
.
default_external
)
end
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/30796
it
'reads in binary, output as Encoding.default_external'
do
stream
.
limit
(
52
)
result
=
stream
.
html
expect
(
result
).
to
eq
(
"ヾ(´༎ຶД༎ຶ`)ノ<br><span class=
\"
term-fg-green
\"
>許功蓋</span><br>"
)
expect
(
result
.
encoding
).
to
eq
(
Encoding
.
default_external
)
end
end
end
...
...
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