Commit 8f4e7544 authored by Fatih Acet's avatar Fatih Acet

Merge branch '21604-pipeline-ui-updates' into 'master'

Update pipeline graph styles to match mockup

#### What does this MR do?
* Updates CSS for pipeline graph to match mockup 
* Adds JS to dynamically change line widths based on number of builds

#### Screenshots (if relevant)
![Screen_Shot_2016-10-04_at_2.06.24_PM](/uploads/362378ca23e18a3cc59185eafab9f9ac/Screen_Shot_2016-10-04_at_2.06.24_PM.png)

#### What are the relevant issue numbers?
Closes #21604

See merge request !6320
parents e17fa240 d87df157
...@@ -126,6 +126,9 @@ ...@@ -126,6 +126,9 @@
new TreeView(); new TreeView();
} }
break; break;
case 'projects:pipelines:show':
new gl.Pipelines();
break;
case 'groups:activity': case 'groups:activity':
new Activities(); new Activities();
break; break;
......
(function() { ((global) => {
function toggleGraph() {
const $pipelineBtn = $(this).closest('.toggle-pipeline-btn'); class Pipelines {
const $pipelineGraph = $(this).closest('.row-content-block').next('.pipeline-graph'); constructor() {
const $btnText = $(this).find('.toggle-btn-text'); $(document).off('click', '.toggle-pipeline-btn').on('click', '.toggle-pipeline-btn', this.toggleGraph);
const $icon = $(this).find('.fa'); this.addMarginToBuildColumns();
}
$($pipelineBtn).add($pipelineGraph).toggleClass('graph-collapsed');
toggleGraph() {
const graphCollapsed = $pipelineGraph.hasClass('graph-collapsed'); const $pipelineBtn = $(this).closest('.toggle-pipeline-btn');
const expandIcon = 'fa-caret-down'; const $pipelineGraph = $(this).closest('.row-content-block').next('.pipeline-graph');
const hideIcon = 'fa-caret-up'; const $btnText = $(this).find('.toggle-btn-text');
const graphCollapsed = $pipelineGraph.hasClass('graph-collapsed');
if(graphCollapsed) {
$btnText.text('Expand'); $($pipelineBtn).add($pipelineGraph).toggleClass('graph-collapsed');
$icon.removeClass(hideIcon).addClass(expandIcon);
} else {
$btnText.text('Hide'); graphCollapsed ? $btnText.text('Expand') : $btnText.text('Hide')
$icon.removeClass(expandIcon).addClass(hideIcon); }
addMarginToBuildColumns() {
const $secondChildBuildNode = $('.build:nth-child(2)');
if ($secondChildBuildNode.length) {
const $firstChildBuildNode = $secondChildBuildNode.prev('.build');
const $multiBuildColumn = $secondChildBuildNode.closest('.stage-column');
const $previousColumn = $multiBuildColumn.prev('.stage-column');
$multiBuildColumn.addClass('left-margin');
$firstChildBuildNode.addClass('left-connector');
$previousColumn.each(function() {
$this = $(this);
if ($('.build', $this).length === 1) $this.addClass('no-margin');
});
}
$('.pipeline-graph').removeClass('hidden');
} }
} }
$(document).on('click', '.toggle-pipeline-btn', toggleGraph); global.Pipelines = Pipelines;
})();
})(window.gl || (window.gl = {}));
...@@ -17,8 +17,10 @@ $white-normal: #ededed; ...@@ -17,8 +17,10 @@ $white-normal: #ededed;
$white-dark: #ececec; $white-dark: #ececec;
$gray-light: #fafafa; $gray-light: #fafafa;
$gray-lighter: #f9f9f9;
$gray-normal: #f5f5f5; $gray-normal: #f5f5f5;
$gray-dark: #ededed; $gray-dark: #ededed;
$gray-darker: #eee;
$gray-darkest: #c9c9c9; $gray-darkest: #c9c9c9;
$green-light: #38ae67; $green-light: #38ae67;
...@@ -33,6 +35,8 @@ $blue-medium-light: #3498cb; ...@@ -33,6 +35,8 @@ $blue-medium-light: #3498cb;
$blue-medium: #2f8ebf; $blue-medium: #2f8ebf;
$blue-medium-dark: #2d86b4; $blue-medium-dark: #2d86b4;
$blue-light-transparent: rgba(44, 159, 216, 0.05);
$orange-light: #fc8a51; $orange-light: #fc8a51;
$orange-normal: #e75e40; $orange-normal: #e75e40;
$orange-dark: #ce5237; $orange-dark: #ce5237;
...@@ -91,6 +95,7 @@ $table-text-gray: #8f8f8f; ...@@ -91,6 +95,7 @@ $table-text-gray: #8f8f8f;
$gl-font-size: 15px; $gl-font-size: 15px;
$gl-title-color: #333; $gl-title-color: #333;
$gl-text-color: #5c5c5c; $gl-text-color: #5c5c5c;
$gl-text-color-light: #8c8c8c;
$gl-text-green: #4a2; $gl-text-green: #4a2;
$gl-text-red: #d12f19; $gl-text-red: #d12f19;
$gl-text-orange: #d90; $gl-text-orange: #d90;
......
...@@ -303,16 +303,41 @@ ...@@ -303,16 +303,41 @@
.stage-column { .stage-column {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin-right: 65px;
&:not(:last-child) {
margin-right: 44px;
}
&.left-margin {
&:not(:first-child) {
margin-left: 44px;
.left-connector {
&::before {
content: '';
position: absolute;
top: 48%;
left: -48px;
border-top: 2px solid $border-color;
width: 48px;
height: 1px;
}
}
}
}
&.no-margin {
margin: 0;
}
li { li {
list-style: none; list-style: none;
} }
.stage-name { .stage-name {
margin-bottom: 15px; margin: 0 0 15px 10px;
font-weight: bold; font-weight: bold;
width: 150px; width: 176px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
...@@ -321,17 +346,23 @@ ...@@ -321,17 +346,23 @@
.build { .build {
border: 1px solid $border-color; border: 1px solid $border-color;
position: relative; position: relative;
padding: 6px 10px; padding: 7px 10px 8px;
border-radius: 30px; border-radius: 30px;
width: 150px; width: 186px;
margin-bottom: 10px; margin-bottom: 10px;
&:hover {
background-color: $gray-lighter;
.dropdown-menu-toggle {
background-color: transparent;
}
}
&.playable { &.playable {
background-color: $gray-light;
svg { svg {
height: 12px; height: 13px;
width: 12px; width: 20px;
position: relative; position: relative;
top: 1px; top: 1px;
...@@ -342,10 +373,20 @@ ...@@ -342,10 +373,20 @@
} }
.build-content { .build-content {
width: 130px; display: -ms-flexbox;
display: -webkit-flex;
display: flex;
width: 164px;
.ci-status-icon {
svg {
height: 20px;
width: 20px;
}
}
.ci-status-text { .ci-status-text {
width: 110px; width: 135px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
...@@ -356,44 +397,53 @@ ...@@ -356,44 +397,53 @@
} }
a { a {
color: $layout-link-gray; color: $gl-text-color-light;
text-decoration: none; text-decoration: none;
&:hover {
.ci-status-text {
text-decoration: underline;
}
}
} }
.dropdown-menu-toggle { .dropdown-menu-toggle {
border: none; border: none;
width: auto; width: auto;
padding: 0; padding: 0;
color: $layout-link-gray; color: $gl-text-color-light;
flex-grow: 1;
.ci-status-text { .ci-status-text {
width: 80px; max-width: 112px;
width: auto;
} }
} }
.grouped-pipeline-dropdown { .grouped-pipeline-dropdown {
padding: 8px 0; padding: 8px 0;
width: 200px; width: 186px;
left: auto; left: auto;
right: -214px; right: -197px;
top: -9px; top: -9px;
max-height: 245px; max-height: 245px;
overflow-y: scroll; overflow-y: scroll;
a:hover { a {
.ci-status-text { color: $gl-text-color;
text-decoration: none; padding: 7px 8px 8px;
&:hover {
background-color: $blue-light-transparent;
border-radius: 3px;
.ci-status-text {
text-decoration: none;
}
} }
} }
svg {
width: 14px;
height: 14px;
}
.ci-status-text { .ci-status-text {
width: 145px; width: 112px;
} }
.arrow { .arrow {
...@@ -426,9 +476,10 @@ ...@@ -426,9 +476,10 @@
} }
.badge { .badge {
background-color: $gray-dark; background-color: $gray-darker;
color: $layout-link-gray; color: $gl-text-color-light;
font-weight: normal; font-weight: normal;
margin-left: $btn-xs-side-margin;
} }
} }
...@@ -442,10 +493,10 @@ ...@@ -442,10 +493,10 @@
&::after { &::after {
content: ''; content: '';
position: absolute; position: absolute;
top: 50%; top: 48%;
right: -69px; right: -48px;
border-top: 2px solid $border-color; border-top: 2px solid $border-color;
width: 69px; width: 48px;
height: 1px; height: 1px;
} }
} }
...@@ -454,25 +505,25 @@ ...@@ -454,25 +505,25 @@
&:not(:first-child) { &:not(:first-child) {
&::after, &::before { &::after, &::before {
content: ''; content: '';
top: -47px; top: -49px;
position: absolute; position: absolute;
border-bottom: 2px solid $border-color; border-bottom: 2px solid $border-color;
width: 20px; width: 25px;
height: 65px; height: 69px;
} }
// Right connecting curves // Right connecting curves
&::after { &::after {
right: -20px; right: -25px;
border-right: 2px solid $border-color; border-right: 2px solid $border-color;
border-radius: 0 0 15px; border-radius: 0 0 20px;
} }
// Left connecting curves // Left connecting curves
&::before { &::before {
left: -20px; left: -25px;
border-left: 2px solid $border-color; border-left: 2px solid $border-color;
border-radius: 0 0 0 15px; border-radius: 0 0 0 20px;
} }
} }
...@@ -480,7 +531,7 @@ ...@@ -480,7 +531,7 @@
&:nth-child(2) { &:nth-child(2) {
&::after, &::before { &::after, &::before {
height: 29px; height: 29px;
top: -10px; top: -9px;
} }
.curve { .curve {
display: block; display: block;
...@@ -538,20 +589,20 @@ ...@@ -538,20 +589,20 @@
width: 21px; width: 21px;
height: 25px; height: 25px;
position: absolute; position: absolute;
top: -29px; top: -32px;
border-top: 2px solid $border-color; border-top: 2px solid $border-color;
} }
&::after { &::after {
left: -39px; left: -44px;
border-right: 2px solid $border-color; border-right: 2px solid $border-color;
border-radius: 0 15px; border-radius: 0 20px;
} }
&::before { &::before {
right: -39px; right: -44px;
border-left: 2px solid $border-color; border-left: 2px solid $border-color;
border-radius: 15px 0 0; border-radius: 20px 0 0;
} }
} }
} }
......
...@@ -5,8 +5,10 @@ ...@@ -5,8 +5,10 @@
.ci-status-text= subject.name .ci-status-text= subject.name
- elsif can?(current_user, :read_build, @project) - elsif can?(current_user, :read_build, @project)
= link_to namespace_project_build_path(subject.project.namespace, subject.project, subject) do = link_to namespace_project_build_path(subject.project.namespace, subject.project, subject) do
= render_status_with_link('build', subject.status) %span.ci-status-icon
= render_status_with_link('build', subject.status)
.ci-status-text= subject.name .ci-status-text= subject.name
- else - else
= render_status_with_link('build', subject.status) %span.ci-status-icon
= render_status_with_link('build', subject.status)
= ci_icon_for_status(subject.status) = ci_icon_for_status(subject.status)
.row-content-block.build-content.middle-block.pipeline-actions .pipeline-graph-container
.pull-right .row-content-block.build-content.middle-block.pipeline-actions
.btn.btn-grouped.btn-white.toggle-pipeline-btn .pull-right
%span.toggle-btn-text Hide .btn.btn-grouped.btn-white.toggle-pipeline-btn
%span pipeline graph %span.toggle-btn-text Hide
= icon('caret-up') %span pipeline graph
- if can?(current_user, :update_pipeline, pipeline.project) %span.caret
- if pipeline.builds.latest.failed.any?(&:retryable?) - if can?(current_user, :update_pipeline, pipeline.project)
= link_to "Retry failed", retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn btn-grouped btn-primary', method: :post - if pipeline.builds.latest.failed.any?(&:retryable?)
= link_to "Retry failed", retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn btn-grouped btn-primary', method: :post
- if pipeline.builds.running_or_pending.any? - if pipeline.builds.running_or_pending.any?
= link_to "Cancel running", cancel_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post = link_to "Cancel running", cancel_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
.oneline.clearfix .oneline.clearfix
- if defined?(pipeline_details) && pipeline_details - if defined?(pipeline_details) && pipeline_details
Pipeline Pipeline
= link_to "##{pipeline.id}", namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "monospace" = link_to "##{pipeline.id}", namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "monospace"
with with
= pluralize pipeline.statuses.count(:id), "build" = pluralize pipeline.statuses.count(:id), "build"
- if pipeline.ref - if pipeline.ref
for for
= link_to pipeline.ref, namespace_project_commits_path(pipeline.project.namespace, pipeline.project, pipeline.ref), class: "monospace" = link_to pipeline.ref, namespace_project_commits_path(pipeline.project.namespace, pipeline.project, pipeline.ref), class: "monospace"
- if defined?(link_to_commit) && link_to_commit - if defined?(link_to_commit) && link_to_commit
for commit for commit
= link_to pipeline.short_sha, namespace_project_commit_path(pipeline.project.namespace, pipeline.project, pipeline.sha), class: "monospace" = link_to pipeline.short_sha, namespace_project_commit_path(pipeline.project.namespace, pipeline.project, pipeline.sha), class: "monospace"
- if pipeline.duration - if pipeline.duration
in in
= time_interval_in_words pipeline.duration = time_interval_in_words pipeline.duration
.row-content-block.build-content.middle-block.pipeline-graph .row-content-block.build-content.middle-block.pipeline-graph.hidden
.pipeline-visualization .pipeline-visualization
%ul.stage-column-list %ul.stage-column-list
- stages = pipeline.stages_with_latest_statuses - stages = pipeline.stages_with_latest_statuses
- stages.each do |stage, statuses| - stages.each do |stage, statuses|
%li.stage-column %li.stage-column
.stage-name .stage-name
%a{name: stage} %a{name: stage}
- if stage - if stage
= stage.titleize = stage.titleize
.builds-container .builds-container
%ul %ul
= render "projects/commit/pipeline_stage", statuses: statuses = render "projects/commit/pipeline_stage", statuses: statuses
- if pipeline.yaml_errors.present? - if pipeline.yaml_errors.present?
......
...@@ -10,5 +10,5 @@ ...@@ -10,5 +10,5 @@
- else - else
%li.build %li.build
.curve .curve
.build-content .dropdown.inline.build-content
= render "projects/commit/pipeline_status_group", name: group_name, subject: grouped_statuses = render "projects/commit/pipeline_status_group", name: group_name, subject: grouped_statuses
- group_status = CommitStatus.where(id: subject).status - group_status = CommitStatus.where(id: subject).status
= render_status_with_link('build', group_status) %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown' } }
.dropdown.inline %span.ci-status-icon
%button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown' } } = render_status_with_link('build', group_status)
%span.ci-status-text %span.ci-status-text
= name = name
%span.badge= subject.size %span.badge= subject.size
%ul.dropdown-menu.grouped-pipeline-dropdown %ul.dropdown-menu.grouped-pipeline-dropdown
.arrow %li.arrow
- subject.each do |status| - subject.each do |status|
%li
= render "projects/#{status.to_partial_path}_pipeline", subject: status = render "projects/#{status.to_partial_path}_pipeline", subject: status
...@@ -62,5 +62,3 @@ ...@@ -62,5 +62,3 @@
%td.coverage %td.coverage
- if generic_commit_status.try(:coverage) - if generic_commit_status.try(:coverage)
#{generic_commit_status.coverage}% #{generic_commit_status.coverage}%
%td
- if subject.target_url - if subject.target_url
= link_to subject.target_url do = link_to subject.target_url do
= render_status_with_link('commit status', subject.status) %span.ci-status-icon
= render_status_with_link('commit status', subject.status)
%span.ci-status-text= subject.name %span.ci-status-text= subject.name
- else - else
= render_status_with_link('commit status', subject.status) %span.ci-status-icon
= render_status_with_link('commit status', subject.status)
%span.ci-status-text= subject.name %span.ci-status-text= subject.name
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