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
Boxiang Sun
gitlab-ce
Commits
5a3b2f83
Commit
5a3b2f83
authored
Mar 09, 2017
by
Filipa Lacerda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Uses vanilla JS to listen to click event
Removes `:visible` from selector Adds CHANGELOG entry Removes iife
parent
429eb466
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
97 additions
and
96 deletions
+97
-96
app/assets/javascripts/dispatcher.js
app/assets/javascripts/dispatcher.js
+2
-1
app/assets/javascripts/merge_request_widget.js
app/assets/javascripts/merge_request_widget.js
+3
-2
app/assets/javascripts/mini_pipeline_graph_dropdown.js
app/assets/javascripts/mini_pipeline_graph_dropdown.js
+80
-85
changelogs/unreleased/24166-close-builds-dropdown.yml
changelogs/unreleased/24166-close-builds-dropdown.yml
+4
-0
spec/javascripts/mini_pipeline_graph_dropdown_spec.js
spec/javascripts/mini_pipeline_graph_dropdown_spec.js
+8
-8
No files found.
app/assets/javascripts/dispatcher.js
View file @
5a3b2f83
...
...
@@ -39,6 +39,7 @@ import Issue from './issue';
import
BindInOut
from
'
./behaviors/bind_in_out
'
;
import
GroupsList
from
'
./groups_list
'
;
import
ProjectsList
from
'
./projects_list
'
;
import
MiniPipelineGraph
from
'
./mini_pipeline_graph_dropdown
'
;
const
ShortcutsBlob
=
require
(
'
./shortcuts_blob
'
);
const
UserCallout
=
require
(
'
./user_callout
'
);
...
...
@@ -181,7 +182,7 @@ const UserCallout = require('./user_callout');
shortcut_handler
=
new
ShortcutsNavigation
();
break
;
case
'
projects:commit:pipelines
'
:
new
gl
.
MiniPipelineGraph
({
new
MiniPipelineGraph
({
container
:
'
.js-pipeline-table
'
,
}).
bindEvents
();
break
;
...
...
app/assets/javascripts/merge_request_widget.js
View file @
5a3b2f83
...
...
@@ -4,6 +4,7 @@
/* global merge_request_widget */
require
(
'
./smart_interval
'
);
const
MiniPipelineGraph
=
require
(
'
./mini_pipeline_graph_dropdown
'
).
default
;
((
global
)
=>
{
var
indexOf
=
[].
indexOf
||
function
(
item
)
{
for
(
var
i
=
0
,
l
=
this
.
length
;
i
<
l
;
i
+=
1
)
{
if
(
i
in
this
&&
this
[
i
]
===
item
)
return
i
;
}
return
-
1
;
};
...
...
@@ -285,8 +286,8 @@ require('./smart_interval');
};
MergeRequestWidget
.
prototype
.
initMiniPipelineGraph
=
function
()
{
new
gl
.
MiniPipelineGraph
({
container
:
'
.js-pipeline-inline-mr-widget-graph
:visible
'
,
new
MiniPipelineGraph
({
container
:
'
.js-pipeline-inline-mr-widget-graph
'
,
}).
bindEvents
();
};
...
...
app/assets/javascripts/mini_pipeline_graph_dropdown.js
View file @
5a3b2f83
...
...
@@ -15,97 +15,92 @@
* <div class="js-builds-dropdown-container dropdown-menu"></div>
* </div>
*/
(()
=>
{
class
MiniPipelineGraph
{
constructor
(
opts
=
{})
{
this
.
container
=
opts
.
container
||
''
;
this
.
dropdownListSelector
=
'
.js-builds-dropdown-container
'
;
this
.
getBuildsList
=
this
.
getBuildsList
.
bind
(
this
);
this
.
stopDropdownClickPropagation
();
}
/**
* Adds the event listener when the dropdown is opened.
* All dropdown events are fired at the .dropdown-menu's parent element.
*/
bindEvents
()
{
$
(
document
).
off
(
'
shown.bs.dropdown
'
,
this
.
container
).
on
(
'
shown.bs.dropdown
'
,
this
.
container
,
this
.
getBuildsList
);
}
export
default
class
MiniPipelineGraph
{
constructor
(
opts
=
{})
{
this
.
container
=
opts
.
container
||
''
;
this
.
dropdownListSelector
=
'
.js-builds-dropdown-container
'
;
this
.
getBuildsList
=
this
.
getBuildsList
.
bind
(
this
);
}
/**
* When the user right clicks or cmd/ctrl + click in the job name
* the dropdown should not be closed and the link should open in another tab,
* so we stop propagation of the click event inside the dropdown.
*
* Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component.
*/
stopDropdownClickPropagation
()
{
$
(
document
).
on
(
'
click
'
,
`
${
this
.
container
}
.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`
,
(
e
)
=>
{
e
.
stopPropagation
();
});
}
/**
* Adds the event listener when the dropdown is opened.
* All dropdown events are fired at the .dropdown-menu's parent element.
*/
bindEvents
()
{
$
(
document
).
off
(
'
shown.bs.dropdown
'
,
this
.
container
).
on
(
'
shown.bs.dropdown
'
,
this
.
container
,
this
.
getBuildsList
);
}
/**
* For the clicked stage, renders the given data in the dropdown list.
*
* @param {HTMLElement} stageContainer
* @param {Object} data
*/
renderBuildsList
(
stageContainer
,
data
)
{
const
dropdownContainer
=
stageContainer
.
parentElement
.
querySelector
(
`
${
this
.
dropdownListSelector
}
.js-builds-dropdown-list`
,
);
/**
* When the user right clicks or cmd/ctrl + click in the job name
* the dropdown should not be closed and the link should open in another tab,
* so we stop propagation of the click event inside the dropdown.
*
* Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component.
*/
stopDropdownClickPropagation
()
{
document
.
querySelector
(
`
${
this
.
container
}
.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`
).
addEventListener
(
'
click
'
,
(
e
)
=>
{
e
.
stopPropagation
();
});
}
dropdownContainer
.
innerHTML
=
data
;
}
/**
* For the clicked stage, renders the given data in the dropdown list.
*
* @param {HTMLElement} stageContainer
* @param {Object} data
*/
renderBuildsList
(
stageContainer
,
data
)
{
const
dropdownContainer
=
stageContainer
.
parentElement
.
querySelector
(
`
${
this
.
dropdownListSelector
}
.js-builds-dropdown-list`
,
);
/**
* For the clicked stage, gets the list of builds.
*
* All dropdown events have a relatedTarget property,
* whose value is the toggling anchor element.
*
* @param {Object} e bootstrap dropdown event
* @return {Promise}
*/
getBuildsList
(
e
)
{
const
button
=
e
.
relatedTarget
;
const
endpoint
=
button
.
dataset
.
stageEndpoint
;
dropdownContainer
.
innerHTML
=
data
;
}
return
$
.
ajax
({
dataType
:
'
json
'
,
type
:
'
GET
'
,
url
:
endpoint
,
beforeSend
:
()
=>
{
this
.
renderBuildsList
(
button
,
''
);
this
.
toggleLoading
(
button
);
},
success
:
(
data
)
=>
{
this
.
toggleLoading
(
button
);
this
.
renderBuildsList
(
button
,
data
.
html
);
},
error
:
()
=>
{
this
.
toggleLoading
(
button
);
new
Flash
(
'
An error occurred while fetching the builds.
'
,
'
alert
'
);
},
});
}
/**
* For the clicked stage, gets the list of builds.
*
* All dropdown events have a relatedTarget property,
* whose value is the toggling anchor element.
*
* @param {Object} e bootstrap dropdown event
* @return {Promise}
*/
getBuildsList
(
e
)
{
const
button
=
e
.
relatedTarget
;
const
endpoint
=
button
.
dataset
.
stageEndpoint
;
/**
* Toggles the visibility of the loading icon.
*
* @param {HTMLElement} stageContainer
* @return {type}
*/
toggleLoading
(
stageContainer
)
{
stageContainer
.
parentElement
.
querySelector
(
`
${
this
.
dropdownListSelector
}
.js-builds-dropdown-loading`
,
).
classList
.
toggle
(
'
hidden
'
);
}
return
$
.
ajax
({
dataType
:
'
json
'
,
type
:
'
GET
'
,
url
:
endpoint
,
beforeSend
:
()
=>
{
this
.
renderBuildsList
(
button
,
''
);
this
.
toggleLoading
(
button
);
},
success
:
(
data
)
=>
{
this
.
toggleLoading
(
button
);
this
.
renderBuildsList
(
button
,
data
.
html
);
this
.
stopDropdownClickPropagation
();
},
error
:
()
=>
{
this
.
toggleLoading
(
button
);
new
Flash
(
'
An error occurred while fetching the builds.
'
,
'
alert
'
);
},
});
}
window
.
gl
=
window
.
gl
||
{};
window
.
gl
.
MiniPipelineGraph
=
MiniPipelineGraph
;
})();
/**
* Toggles the visibility of the loading icon.
*
* @param {HTMLElement} stageContainer
* @return {type}
*/
toggleLoading
(
stageContainer
)
{
stageContainer
.
parentElement
.
querySelector
(
`
${
this
.
dropdownListSelector
}
.js-builds-dropdown-loading`
,
).
classList
.
toggle
(
'
hidden
'
);
}
}
changelogs/unreleased/24166-close-builds-dropdown.yml
0 → 100644
View file @
5a3b2f83
---
title
:
Prevent builds dropdown to close when the user clicks in a build
merge_request
:
author
:
spec/javascripts/mini_pipeline_graph_dropdown_spec.js
View file @
5a3b2f83
/* eslint-disable no-new */
require
(
'
~/flash
'
)
;
require
(
'
~/mini_pipeline_graph_dropdown
'
)
;
import
MiniPipelineGraph
from
'
~/mini_pipeline_graph_dropdown
'
;
import
'
~/flash
'
;
(()
=>
{
describe
(
'
Mini Pipeline Graph Dropdown
'
,
()
=>
{
...
...
@@ -13,7 +13,7 @@ require('~/mini_pipeline_graph_dropdown');
describe
(
'
When is initialized
'
,
()
=>
{
it
(
'
should initialize without errors when no options are given
'
,
()
=>
{
const
miniPipelineGraph
=
new
window
.
gl
.
MiniPipelineGraph
();
const
miniPipelineGraph
=
new
MiniPipelineGraph
();
expect
(
miniPipelineGraph
.
dropdownListSelector
).
toEqual
(
'
.js-builds-dropdown-container
'
);
});
...
...
@@ -21,7 +21,7 @@ require('~/mini_pipeline_graph_dropdown');
it
(
'
should set the container as the given prop
'
,
()
=>
{
const
container
=
'
.foo
'
;
const
miniPipelineGraph
=
new
window
.
gl
.
MiniPipelineGraph
({
container
});
const
miniPipelineGraph
=
new
MiniPipelineGraph
({
container
});
expect
(
miniPipelineGraph
.
container
).
toEqual
(
container
);
});
...
...
@@ -29,9 +29,9 @@ require('~/mini_pipeline_graph_dropdown');
describe
(
'
When dropdown is clicked
'
,
()
=>
{
it
(
'
should call getBuildsList
'
,
()
=>
{
const
getBuildsListSpy
=
spyOn
(
gl
.
MiniPipelineGraph
.
prototype
,
'
getBuildsList
'
).
and
.
callFake
(
function
()
{});
const
getBuildsListSpy
=
spyOn
(
MiniPipelineGraph
.
prototype
,
'
getBuildsList
'
).
and
.
callFake
(
function
()
{});
new
gl
.
MiniPipelineGraph
({
container
:
'
.js-builds-dropdown-tests
'
}).
bindEvents
();
new
MiniPipelineGraph
({
container
:
'
.js-builds-dropdown-tests
'
}).
bindEvents
();
document
.
querySelector
(
'
.js-builds-dropdown-button
'
).
click
();
...
...
@@ -41,7 +41,7 @@ require('~/mini_pipeline_graph_dropdown');
it
(
'
should make a request to the endpoint provided in the html
'
,
()
=>
{
const
ajaxSpy
=
spyOn
(
$
,
'
ajax
'
).
and
.
callFake
(
function
()
{});
new
gl
.
MiniPipelineGraph
({
container
:
'
.js-builds-dropdown-tests
'
}).
bindEvents
();
new
MiniPipelineGraph
({
container
:
'
.js-builds-dropdown-tests
'
}).
bindEvents
();
document
.
querySelector
(
'
.js-builds-dropdown-button
'
).
click
();
expect
(
ajaxSpy
.
calls
.
allArgs
()[
0
][
0
].
url
).
toEqual
(
'
foobar
'
);
...
...
@@ -53,7 +53,7 @@ require('~/mini_pipeline_graph_dropdown');
html
:
'
\
u003cli
\
u003e
\n\
u003ca class="mini-pipeline-graph-dropdown-item" href="#"
\
u003e
\
u003cspan class="ci-status-icon ci-status-icon-failed"
\
u003e
\
u003c/span
\
u003e
\n\
u003cspan class="ci-build-text"
\
u003ebuild
\
u003c/span
\
u003e
\n\
u003c/a
\
u003e
\
u003ca class="ci-action-icon-wrapper js-ci-action-icon" href="#"
\
u003e
\
u003c/a
\
u003e
\n\
u003c/li
\
u003e
\n
'
,
});
});
new
gl
.
MiniPipelineGraph
({
container
:
'
.js-builds-dropdown-tests
'
}).
bindEvents
();
new
MiniPipelineGraph
({
container
:
'
.js-builds-dropdown-tests
'
}).
bindEvents
();
document
.
querySelector
(
'
.js-builds-dropdown-button
'
).
click
();
...
...
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