BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
065825b7
Commit
065825b7
authored
Mar 10, 2017
by
Clement Ho
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '24166-close-builds-dropdown' into 'master'
Prevent dropdown from closing when user clicks in a build. Closes #24166 See merge request !9834
parents
81ad6111
9275603d
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
122 additions
and
80 deletions
+122
-80
dispatcher.js
app/assets/javascripts/dispatcher.js
+2
-1
merge_request_widget.js
app/assets/javascripts/merge_request_widget.js
+3
-2
mini_pipeline_graph_dropdown.js
app/assets/javascripts/mini_pipeline_graph_dropdown.js
+85
-70
24166-close-builds-dropdown.yml
changelogs/unreleased/24166-close-builds-dropdown.yml
+4
-0
mini_pipeline_graph_dropdown_spec.js
spec/javascripts/mini_pipeline_graph_dropdown_spec.js
+28
-7
No files found.
app/assets/javascripts/dispatcher.js
View file @
065825b7
...
...
@@ -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 @
065825b7
...
...
@@ -3,7 +3,8 @@
/* global notifyPermissions */
/* global merge_request_widget */
require
(
'./smart_interval'
);
import
'./smart_interval'
;
import
MiniPipelineGraph
from
'./mini_pipeline_graph_dropdown'
;
((
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,7 +286,7 @@ require('./smart_interval');
};
MergeRequestWidget
.
prototype
.
initMiniPipelineGraph
=
function
()
{
new
gl
.
MiniPipelineGraph
({
new
MiniPipelineGraph
({
container
:
'.js-pipeline-inline-mr-widget-graph:visible'
,
}).
bindEvents
();
};
...
...
app/assets/javascripts/mini_pipeline_graph_dropdown.js
View file @
065825b7
...
...
@@ -15,81 +15,96 @@
* <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
);
}
/**
* 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
);
}
/**
* 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
).
on
(
'click'
,
`
${
this
.
container
}
.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`
,
(
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 @
065825b7
---
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 @
065825b7
/* 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,11 +41,32 @@ 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'
);
});
it
(
'should not close when user uses cmd/ctrl + click'
,
()
=>
{
spyOn
(
$
,
'ajax'
).
and
.
callFake
(
function
(
params
)
{
params
.
success
({
html
:
`<li>
<a class="mini-pipeline-graph-dropdown-item" href="#">
<span class="ci-status-icon ci-status-icon-failed"></span>
<span class="ci-build-text">build</span>
</a>
<a class="ci-action-icon-wrapper js-ci-action-icon" href="#"></a>
</li>`
,
});
});
new
MiniPipelineGraph
({
container
:
'.js-builds-dropdown-tests'
}).
bindEvents
();
document
.
querySelector
(
'.js-builds-dropdown-button'
).
click
();
document
.
querySelector
(
'a.mini-pipeline-graph-dropdown-item'
).
click
();
expect
(
$
(
'.js-builds-dropdown-list'
).
is
(
':visible'
)).
toEqual
(
true
);
});
});
});
})();
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