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
a0d0ffe5
Commit
a0d0ffe5
authored
Jan 14, 2017
by
Luke "Jared" Bennett
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added inline pipeline graph
Added tests review changes
parent
1bbc99f1
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
238 additions
and
75 deletions
+238
-75
app/assets/javascripts/dispatcher.js.es6
app/assets/javascripts/dispatcher.js.es6
+5
-0
app/assets/javascripts/merge_request_widget.js.es6
app/assets/javascripts/merge_request_widget.js.es6
+16
-4
app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6
app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6
+0
-2
app/assets/stylesheets/pages/merge_requests.scss
app/assets/stylesheets/pages/merge_requests.scss
+43
-0
app/assets/stylesheets/pages/pipelines.scss
app/assets/stylesheets/pages/pipelines.scss
+42
-42
app/views/projects/ci/pipelines/_pipeline.html.haml
app/views/projects/ci/pipelines/_pipeline.html.haml
+2
-19
app/views/projects/merge_requests/widget/_heading.html.haml
app/views/projects/merge_requests/widget/_heading.html.haml
+10
-6
app/views/shared/_mini_pipeline_graph.html.haml
app/views/shared/_mini_pipeline_graph.html.haml
+18
-0
spec/features/merge_requests/mini_pipeline_graph_spec.rb
spec/features/merge_requests/mini_pipeline_graph_spec.rb
+100
-0
spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6
spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6
+2
-2
No files found.
app/assets/javascripts/dispatcher.js.es6
View file @
a0d0ffe5
...
@@ -159,6 +159,11 @@
...
@@ -159,6 +159,11 @@
new ZenMode();
new ZenMode();
shortcut_handler = new ShortcutsNavigation();
shortcut_handler = new ShortcutsNavigation();
break;
break;
case 'projects:commit:pipelines':
new gl.MiniPipelineGraph({
container: '.js-pipeline-table',
}).bindEvents();
break;
case 'projects:commits:show':
case 'projects:commits:show':
case 'projects:activity':
case 'projects:activity':
shortcut_handler = new ShortcutsNavigation();
shortcut_handler = new ShortcutsNavigation();
...
...
app/assets/javascripts/merge_request_widget.js.es6
View file @
a0d0ffe5
...
@@ -51,6 +51,8 @@ require('./smart_interval');
...
@@ -51,6 +51,8 @@ require('./smart_interval');
this.getCIStatus(false);
this.getCIStatus(false);
this.retrieveSuccessIcon();
this.retrieveSuccessIcon();
this.initMiniPipelineGraph();
this.ciStatusInterval = new global.SmartInterval({
this.ciStatusInterval = new global.SmartInterval({
callback: this.getCIStatus.bind(this, true),
callback: this.getCIStatus.bind(this, true),
startingInterval: 10000,
startingInterval: 10000,
...
@@ -66,6 +68,7 @@ require('./smart_interval');
...
@@ -66,6 +68,7 @@ require('./smart_interval');
incrementByFactorOf: 15000,
incrementByFactorOf: 15000,
immediateExecution: true,
immediateExecution: true,
});
});
notifyPermissions();
notifyPermissions();
}
}
...
@@ -236,17 +239,20 @@ require('./smart_interval');
...
@@ -236,17 +239,20 @@ require('./smart_interval');
case "failed":
case "failed":
case "canceled":
case "canceled":
case "not_found":
case "not_found":
return this.setMergeButtonClass('btn-danger');
this.setMergeButtonClass('btn-danger');
break;
case "running":
case "running":
return this.setMergeButtonClass('btn-info');
this.setMergeButtonClass('btn-info');
break;
case "success":
case "success":
case "success_with_warnings":
case "success_with_warnings":
return
this.setMergeButtonClass('btn-create');
this.setMergeButtonClass('btn-create');
}
}
} else {
} else {
$('.ci_widget.ci-error').show();
$('.ci_widget.ci-error').show();
return
this.setMergeButtonClass('btn-danger');
this.setMergeButtonClass('btn-danger');
}
}
this.initMiniPipelineGraph();
};
};
MergeRequestWidget.prototype.showCICoverage = function(coverage) {
MergeRequestWidget.prototype.showCICoverage = function(coverage) {
...
@@ -269,6 +275,12 @@ require('./smart_interval');
...
@@ -269,6 +275,12 @@ require('./smart_interval');
$('.js-commit-link').text(`#${id}`).attr('href', [commitsUrl, id].join('/'));
$('.js-commit-link').text(`#${id}`).attr('href', [commitsUrl, id].join('/'));
};
};
MergeRequestWidget.prototype.initMiniPipelineGraph = function() {
new gl.MiniPipelineGraph({
container: '.js-pipeline-inline-mr-widget-graph:visible',
}).bindEvents();
};
return MergeRequestWidget;
return MergeRequestWidget;
})();
})();
})(window.gl || (window.gl = {}));
})(window.gl || (window.gl = {}));
app/assets/javascripts/mini_pipeline_graph_dropdown.js.es6
View file @
a0d0ffe5
...
@@ -21,8 +21,6 @@
...
@@ -21,8 +21,6 @@
this.container = opts.container || '';
this.container = opts.container || '';
this.dropdownListSelector = '.js-builds-dropdown-container';
this.dropdownListSelector = '.js-builds-dropdown-container';
this.getBuildsList = this.getBuildsList.bind(this);
this.getBuildsList = this.getBuildsList.bind(this);
this.bindEvents();
}
}
/**
/**
...
...
app/assets/stylesheets/pages/merge_requests.scss
View file @
a0d0ffe5
...
@@ -80,6 +80,10 @@
...
@@ -80,6 +80,10 @@
.ci_widget
{
.ci_widget
{
border-bottom
:
1px
solid
$well-inner-border
;
border-bottom
:
1px
solid
$well-inner-border
;
color
:
$gl-text-color
;
color
:
$gl-text-color
;
display
:
-
webkit-flex
;
display
:
flex
;
-webkit-align-items
:
center
;
align-items
:
center
;
svg
{
svg
{
margin-right
:
4px
;
margin-right
:
4px
;
...
@@ -88,12 +92,20 @@
...
@@ -88,12 +92,20 @@
overflow
:
visible
;
overflow
:
visible
;
}
}
&
>
span
{
padding-right
:
4px
;
}
&
.ci-success_with_warnings
{
&
.ci-success_with_warnings
{
i
{
i
{
color
:
$gl-warning
;
color
:
$gl-warning
;
}
}
}
}
@media
(
max-width
:
$screen-xs-max
)
{
flex-wrap
:
wrap
;
}
}
}
.mr-widget-body
,
.mr-widget-body
,
...
@@ -102,6 +114,37 @@
...
@@ -102,6 +114,37 @@
padding
:
$gl-padding
;
padding
:
$gl-padding
;
}
}
.mr-widget-pipeline-graph
{
flex-shrink
:
0
;
.dropdown-menu
{
margin-top
:
11px
;
}
.ci-action-icon-wrapper
{
line-height
:
16px
;
}
@media
(
max-width
:
$screen-xs-max
)
{
order
:
1
;
margin-top
:
$gl-padding-top
;
border-radius
:
3px
;
background-color
:
$white-light
;
border
:
1px
solid
$gray-darker
;
width
:
100%
;
text-align
:
center
;
.dropdown-menu
{
margin-left
:
-97
.5px
;
}
.
arrow-up
:
:
before
,
.
arrow-up
::
after
,
{
margin-left
:
97
.5px
;
}
}
}
.normal
{
.normal
{
color
:
$gl-text-color
;
color
:
$gl-text-color
;
}
}
...
...
app/assets/stylesheets/pages/pipelines.scss
View file @
a0d0ffe5
...
@@ -183,48 +183,6 @@
...
@@ -183,48 +183,6 @@
}
}
}
}
.stage-cell
{
font-size
:
0
;
padding
:
10px
4px
;
>
.stage-container
>
div
>
button
>
span
>
svg
,
>
.stage-container
>
button
>
svg
{
height
:
22px
;
width
:
22px
;
position
:
absolute
;
top
:
-1px
;
left
:
-1px
;
z-index
:
2
;
overflow
:
visible
;
}
.stage-container
{
display
:
inline-block
;
position
:
relative
;
height
:
22px
;
margin
:
3px
6px
3px
0
;
.tooltip
{
white-space
:
nowrap
;
}
.tooltip-inner
{
padding
:
3px
4px
;
}
&
:not
(
:last-child
)
{
&
:
:
after
{
content
:
''
;
width
:
7px
;
position
:
absolute
;
right
:
-7px
;
top
:
10px
;
border-bottom
:
2px
solid
$border-color
;
}
}
}
}
.duration
,
.duration
,
.finished-at
{
.finished-at
{
color
:
$gl-text-color-secondary
;
color
:
$gl-text-color-secondary
;
...
@@ -311,6 +269,48 @@
...
@@ -311,6 +269,48 @@
}
}
}
}
.stage-cell
{
font-size
:
0
;
padding
:
10px
4px
;
>
.stage-container
>
div
>
button
>
span
>
svg
,
>
.stage-container
>
button
>
svg
{
height
:
22px
;
width
:
22px
;
position
:
absolute
;
top
:
-1px
;
left
:
-1px
;
z-index
:
2
;
overflow
:
visible
;
}
.stage-container
{
display
:
inline-block
;
position
:
relative
;
height
:
22px
;
margin
:
3px
6px
3px
0
;
.tooltip
{
white-space
:
nowrap
;
}
.tooltip-inner
{
padding
:
3px
4px
;
}
&
:not
(
:last-child
)
{
&
:
:
after
{
content
:
''
;
width
:
7px
;
position
:
absolute
;
right
:
-7px
;
top
:
10px
;
border-bottom
:
2px
solid
$border-color
;
}
}
}
}
.admin-builds-table
{
.admin-builds-table
{
.ci-table
td
:last-child
{
.ci-table
td
:last-child
{
min-width
:
120px
;
min-width
:
120px
;
...
...
app/views/projects/ci/pipelines/_pipeline.html.haml
View file @
a0d0ffe5
...
@@ -40,25 +40,8 @@
...
@@ -40,25 +40,8 @@
-
else
-
else
Cant find HEAD commit for this branch
Cant find HEAD commit for this branch
%td
.stage-cell
%td
-
pipeline
.
stages
.
each
do
|
stage
|
=
render
'shared/mini_pipeline_graph'
,
pipeline:
pipeline
,
klass:
'js-mini-pipeline-graph'
-
if
stage
.
status
-
detailed_status
=
stage
.
detailed_status
(
current_user
)
-
icon_status
=
"
#{
detailed_status
.
icon
}
_borderless"
-
status_klass
=
"ci-status-icon ci-status-icon-
#{
detailed_status
.
group
}
"
.stage-container.dropdown.js-mini-pipeline-graph
%button
.mini-pipeline-graph-dropdown-toggle.has-tooltip.js-builds-dropdown-button
{
class:
"ci-status-icon-#{detailed_status.group}"
,
type:
'button'
,
data:
{
toggle:
'dropdown'
,
title:
"#{stage.name}: #{detailed_status.label}"
,
placement:
'top'
,
"stage-endpoint"
=>
stage_namespace_project_pipeline_path
(
pipeline
.
project
.
namespace
,
pipeline
.
project
,
pipeline
,
stage:
stage
.
name
)
}
}
=
custom_icon
(
icon_status
)
=
icon
(
'caret-down'
)
%ul
.dropdown-menu.mini-pipeline-graph-dropdown-menu.js-builds-dropdown-container
.arrow-up
.js-builds-dropdown-list.scrollable-menu
.js-builds-dropdown-loading.builds-dropdown-loading.hidden
%span
.fa.fa-spinner.fa-spin
%td
%td
-
if
pipeline
.
duration
-
if
pipeline
.
duration
...
...
app/views/projects/merge_requests/widget/_heading.html.haml
View file @
a0d0ffe5
-
if
@pipeline
-
if
@pipeline
.mr-widget-heading
.mr-widget-heading
-
%w[success success_with_warnings skipped canceled failed running pending]
.
each
do
|
status
|
-
%w[success success_with_warnings skipped canceled failed running pending]
.
each
do
|
status
|
.ci_widget
{
class:
"ci-#{status} ci-status-icon-#{status}"
,
style:
(
"display:none"
unless
@pipeline
.
status
==
status
)
}
.ci_widget
{
class:
"ci-#{status}"
,
style:
(
"display:none"
unless
@pipeline
.
status
==
status
)
}
=
link_to
namespace_project_pipeline_path
(
@pipeline
.
project
.
namespace
,
@pipeline
.
project
,
@pipeline
.
id
),
class:
'icon-link'
do
%div
{
class:
"ci-status-icon-#{status}"
}
=
ci_icon_for_status
(
status
)
=
link_to
namespace_project_pipeline_path
(
@pipeline
.
project
.
namespace
,
@pipeline
.
project
,
@pipeline
.
id
),
class:
'icon-link'
do
=
ci_icon_for_status
(
status
)
%span
%span
Pipeline
Pipeline
=
link_to
"#
#{
@pipeline
.
id
}
"
,
namespace_project_pipeline_path
(
@pipeline
.
project
.
namespace
,
@pipeline
.
project
,
@pipeline
.
id
),
class:
'pipeline'
=
link_to
"#
#{
@pipeline
.
id
}
"
,
namespace_project_pipeline_path
(
@pipeline
.
project
.
namespace
,
@pipeline
.
project
,
@pipeline
.
id
),
class:
'pipeline'
=
ci_label_for_status
(
status
)
=
ci_label_for_status
(
status
)
for
.mr-widget-pipeline-graph
=
succeed
"."
do
=
render
'shared/mini_pipeline_graph'
,
pipeline:
@pipeline
,
klass:
'js-pipeline-inline-mr-widget-graph'
=
link_to
@pipeline
.
short_sha
,
namespace_project_commit_path
(
@merge_request
.
source_project
.
namespace
,
@merge_request
.
source_project
,
@pipeline
.
sha
),
class:
"monospace js-commit-link"
%span
for
=
succeed
"."
do
=
link_to
@pipeline
.
short_sha
,
namespace_project_commit_path
(
@merge_request
.
source_project
.
namespace
,
@merge_request
.
source_project
,
@pipeline
.
sha
),
class:
"monospace js-commit-link"
%span
.ci-coverage
%span
.ci-coverage
-
elsif
@merge_request
.
has_ci?
-
elsif
@merge_request
.
has_ci?
...
...
app/views/shared/_mini_pipeline_graph.html.haml
0 → 100644
View file @
a0d0ffe5
.stage-cell
-
pipeline
.
stages
.
each
do
|
stage
|
-
if
stage
.
status
-
detailed_status
=
stage
.
detailed_status
(
current_user
)
-
icon_status
=
"
#{
detailed_status
.
icon
}
_borderless"
-
status_klass
=
"ci-status-icon ci-status-icon-
#{
detailed_status
.
group
}
"
.stage-container.dropdown
{
class:
klass
}
%button
.mini-pipeline-graph-dropdown-toggle.has-tooltip.js-builds-dropdown-button
{
class:
"ci-status-icon-#{detailed_status.group}"
,
type:
'button'
,
data:
{
toggle:
'dropdown'
,
title:
"#{stage.name}: #{detailed_status.label}"
,
placement:
'top'
,
"stage-endpoint"
=>
stage_namespace_project_pipeline_path
(
pipeline
.
project
.
namespace
,
pipeline
.
project
,
pipeline
,
stage:
stage
.
name
)
}
}
=
custom_icon
(
icon_status
)
=
icon
(
'caret-down'
)
%ul
.dropdown-menu.mini-pipeline-graph-dropdown-menu.js-builds-dropdown-container
.arrow-up
.js-builds-dropdown-list.scrollable-menu
.js-builds-dropdown-loading.builds-dropdown-loading.hidden
%span
.fa.fa-spinner.fa-spin
spec/features/merge_requests/mini_pipeline_graph_spec.rb
0 → 100644
View file @
a0d0ffe5
require
'rails_helper'
feature
'Mini Pipeline Graph'
,
:js
,
:feature
do
include
WaitForAjax
let
(
:user
)
{
create
(
:user
)
}
let
(
:project
)
{
create
(
:project
,
:public
)
}
let
(
:merge_request
)
{
create
(
:merge_request
,
source_project:
project
)
}
let
(
:pipeline
)
{
create
(
:ci_empty_pipeline
,
project:
project
,
ref:
'master'
,
status:
'running'
,
sha:
project
.
commit
.
id
)
}
let
(
:build
)
{
create
(
:ci_build
,
pipeline:
pipeline
,
stage:
'test'
,
commands:
'test'
)
}
before
do
build
.
run
login_as
(
user
)
visit
namespace_project_merge_request_path
(
project
.
namespace
,
project
,
merge_request
)
end
it
'should display a mini pipeline graph'
do
expect
(
page
).
to
have_selector
(
'.mr-widget-pipeline-graph'
)
end
describe
'build list toggle'
do
let
(
:toggle
)
do
find
(
'.mini-pipeline-graph-dropdown-toggle'
)
first
(
'.mini-pipeline-graph-dropdown-toggle'
)
end
it
'should expand when hovered'
do
before_width
=
evaluate_script
(
"$('.mini-pipeline-graph-dropdown-toggle:visible').outerWidth();"
)
toggle
.
hover
after_width
=
evaluate_script
(
"$('.mini-pipeline-graph-dropdown-toggle:visible').outerWidth();"
)
expect
(
before_width
).
to
be
<
after_width
end
it
'should show dropdown caret when hovered'
do
toggle
.
hover
expect
(
toggle
).
to
have_selector
(
'.fa-caret-down'
)
end
it
'should show tooltip when hovered'
do
toggle
.
hover
expect
(
toggle
.
find
(
:xpath
,
'..'
)).
to
have_selector
(
'.tooltip'
)
end
end
describe
'builds list menu'
do
let
(
:toggle
)
do
find
(
'.mini-pipeline-graph-dropdown-toggle'
)
first
(
'.mini-pipeline-graph-dropdown-toggle'
)
end
before
do
toggle
.
click
wait_for_ajax
end
it
'should open when toggle is clicked'
do
expect
(
toggle
.
find
(
:xpath
,
'..'
)).
to
have_selector
(
'.mini-pipeline-graph-dropdown-menu'
)
end
it
'should close when toggle is clicked again'
do
toggle
.
click
expect
(
toggle
.
find
(
:xpath
,
'..'
)).
not_to
have_selector
(
'.mini-pipeline-graph-dropdown-menu'
)
end
it
'should close when clicking somewhere else'
do
find
(
'body'
).
click
expect
(
toggle
.
find
(
:xpath
,
'..'
)).
not_to
have_selector
(
'.mini-pipeline-graph-dropdown-menu'
)
end
describe
'build list build item'
do
let
(
:build_item
)
do
find
(
'.mini-pipeline-graph-dropdown-item'
)
first
(
'.mini-pipeline-graph-dropdown-item'
)
end
it
'should visit the build page when clicked'
do
build_item
.
click
find
(
'.build-page'
)
expect
(
current_path
).
to
eql
(
namespace_project_build_path
(
project
.
namespace
,
project
,
build
))
end
it
'should show tooltip when hovered'
do
build_item
.
hover
expect
(
build_item
.
find
(
:xpath
,
'..'
)).
to
have_selector
(
'.tooltip'
)
end
end
end
end
spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6
View file @
a0d0ffe5
...
@@ -31,7 +31,7 @@ require('~/mini_pipeline_graph_dropdown');
...
@@ -31,7 +31,7 @@ require('~/mini_pipeline_graph_dropdown');
it('should call getBuildsList', () => {
it('should call getBuildsList', () => {
const getBuildsListSpy = spyOn(gl.MiniPipelineGraph.prototype, 'getBuildsList').and.callFake(function () {});
const getBuildsListSpy = spyOn(gl.MiniPipelineGraph.prototype, 'getBuildsList').and.callFake(function () {});
new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' });
new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' })
.bindEvents()
;
document.querySelector('.js-builds-dropdown-button').click();
document.querySelector('.js-builds-dropdown-button').click();
...
@@ -41,7 +41,7 @@ require('~/mini_pipeline_graph_dropdown');
...
@@ -41,7 +41,7 @@ require('~/mini_pipeline_graph_dropdown');
it('should make a request to the endpoint provided in the html', () => {
it('should make a request to the endpoint provided in the html', () => {
const ajaxSpy = spyOn($, 'ajax').and.callFake(function () {});
const ajaxSpy = spyOn($, 'ajax').and.callFake(function () {});
new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' });
new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' })
.bindEvents()
;
document.querySelector('.js-builds-dropdown-button').click();
document.querySelector('.js-builds-dropdown-button').click();
expect(ajaxSpy.calls.allArgs()[0][0].url).toEqual('foobar');
expect(ajaxSpy.calls.allArgs()[0][0].url).toEqual('foobar');
...
...
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