Commit cd85baf5 authored by Annabel Dunstone Gray's avatar Annabel Dunstone Gray

Merge branch 'pipelines-graph-html-css' into 'master'

Pipelines graph HTML and CSS improvements  and bug fixing

Closes #26257

See merge request !8443
parents 3b8c81fe d1fc4ec0
...@@ -525,3 +525,4 @@ Pipeline Graph ...@@ -525,3 +525,4 @@ Pipeline Graph
*/ */
$stage-hover-bg: #eaf3fc; $stage-hover-bg: #eaf3fc;
$stage-hover-border: #d1e7fc; $stage-hover-border: #d1e7fc;
$action-icon-color: #d6d6d6;
...@@ -177,12 +177,13 @@ ...@@ -177,12 +177,13 @@
.stage-cell { .stage-cell {
font-size: 0; font-size: 0;
svg { > .stage-container > button > svg {
height: 18px; height: 22px;
width: 18px; width: 22px;
position: relative; position: absolute;
top: -1px;
left: -1px;
z-index: 2; z-index: 2;
vertical-align: middle;
overflow: visible; overflow: visible;
} }
...@@ -200,7 +201,7 @@ ...@@ -200,7 +201,7 @@
content: ''; content: '';
width: 8px; width: 8px;
position: absolute; position: absolute;
right: -7px; right: -8px;
top: 10px; top: 10px;
border-bottom: 2px solid $border-color; border-bottom: 2px solid $border-color;
} }
...@@ -338,7 +339,8 @@ ...@@ -338,7 +339,8 @@
white-space: nowrap; white-space: nowrap;
transition: max-height 0.3s, padding 0.3s; transition: max-height 0.3s, padding 0.3s;
ul { .stage-column-list,
.builds-container > ul {
padding: 0; padding: 0;
} }
...@@ -470,6 +472,47 @@ ...@@ -470,6 +472,47 @@
white-space: normal; white-space: normal;
color: $gl-text-color-secondary; color: $gl-text-color-secondary;
// Action Icons in big pipeline-graph nodes
> .ci-action-icon-container .ci-action-icon-wrapper {
i {
color: $border-color;
border-radius: 100%;
border: 1px solid $border-color;
padding: 5px 6px;
font-size: 13px;
background: $white-light;
height: 30px;
width: 30px;
&::before {
position: relative;
top: 3px;
left: 3px;
}
&:hover {
color: $gl-text-color;
background-color: $stage-hover-bg;
border: 1px solid $stage-hover-bg;
}
}
.ci-play-icon {
padding: 5px 5px 5px 7px;
}
}
> .ci-action-icon-container {
position: absolute;
right: 5px;
top: 5px;
}
.ci-status-icon svg {
height: 20px;
width: 20px;
}
.dropdown-menu-toggle { .dropdown-menu-toggle {
background-color: transparent; background-color: transparent;
border: none; border: none;
...@@ -504,16 +547,6 @@ ...@@ -504,16 +547,6 @@
} }
} }
> .ci-action-icon-container {
position: absolute;
right: 5px;
top: 5px;
}
.ci-status-icon svg {
height: 20px;
width: 20px;
}
.arrow { .arrow {
&::before, &::before,
...@@ -596,29 +629,9 @@ ...@@ -596,29 +629,9 @@
} }
} }
} }
.grouped-pipeline-dropdown {
.dropdown-build {
.build-content {
width: 100%;
&:hover {
background-color: $stage-hover-bg;
color: $gl-text-color;
}
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
position: absolute;
top: 1px;
right: 8px;
}
}
}
} }
// Triggers the dropdown in the big pipeline graph
.dropdown-counter-badge { .dropdown-counter-badge {
color: $border-color; color: $border-color;
font-weight: 100; font-weight: 100;
...@@ -628,66 +641,6 @@ ...@@ -628,66 +641,6 @@
top: 8px; top: 8px;
} }
.grouped-pipeline-dropdown {
padding: 0;
width: 195px;
min-width: 195px;
left: auto;
right: -195px;
top: -4px;
box-shadow: 0 1px 5px $black-transparent;
a {
display: inline-block;
}
.dropdown-build {
.build-content {
width: 100%;
&:hover {
background-color: $stage-hover-bg;
color: $gl-text-color;
}
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
position: absolute;
margin-top: 3px;
right: 7px;
}
}
ul {
max-height: 245px;
overflow: auto;
margin: 3px 0;
li {
margin: 4px 8px 4px 9px;
padding: 0;
line-height: 1.1;
position: relative;
.ci-action-icon-container:hover {
background-color: transparent;
}
.ci-status-icon {
position: relative;
top: 2px;
}
}
}
}
.pipeline-graph .dropdown-build .ci-status-icon svg {
width: 18px;
height: 18px;
}
.ci-status-text { .ci-status-text {
max-width: 110px; max-width: 110px;
white-space: nowrap; white-space: nowrap;
...@@ -699,177 +652,233 @@ ...@@ -699,177 +652,233 @@
font-weight: 200; font-weight: 200;
} }
// Action Icons // Dropdown button in mini pipeline graph
.ci-action-icon-container .ci-action-icon-wrapper { .mini-pipeline-graph-dropdown-toggle {
i { border-radius: 100px;
color: $border-color; background-color: $white-light;
border-radius: 100%; border-width: 1px;
border: 1px solid $border-color; border-style: solid;
padding: 5px 6px; width: 22px;
font-size: 13px; height: 22px;
background: $white-light; margin: 0;
height: 30px; padding: 0;
width: 30px; transition: all 0.2s linear;
position: relative;
&::before { > .fa.fa-caret-down {
position: relative; position: absolute;
top: 3px; left: 20px;
left: 3px; top: 5px;
} display: inline-block;
visibility: hidden;
opacity: 0;
color: inherit;
font-size: 12px;
transition: visibility 0.1s, opacity 0.1s linear;
}
&:hover { &:active,
color: $gl-text-color; &:focus,
background-color: $stage-hover-bg; &:hover {
border: 1px solid $stage-hover-bg; outline: none;
width: 35px;
.fa.fa-caret-down {
visibility: visible;
opacity: 1;
} }
} }
.ci-play-icon { // Dropdown button animation in mini pipeline graph
padding: 5px 5px 5px 7px; &.ci-status-icon-success {
border-color: $gl-success;
color: $gl-success;
&:hover,
&:focus,
&:active {
background-color: rgba($gl-success, 0.1);
border-color: $gl-success;
}
} }
}
.dropdown-build { &.ci-status-icon-failed {
color: $gl-text-color-secondary; border-color: $gl-danger;
color: $gl-danger;
.build-content { &:hover,
padding: 4px 7px 8px; &:focus,
&:active {
background-color: rgba($gl-danger, 0.1);
border-color: $gl-danger;
}
} }
.ci-action-icon-container { &.ci-status-icon-pending,
padding: 0; &.ci-status-icon-success_with_warnings {
font-size: 11px; border-color: $gl-warning;
float: right; color: $gl-warning;
margin-top: 3px;
display: inline-block;
position: relative;
i { &:hover,
font-size: 11px; &:focus,
margin-top: 0; &:active {
background-color: rgba($gl-warning, 0.1);
border-color: $gl-warning;
} }
} }
.ci-action-icon-container { &.ci-status-icon-running {
i { border-color: $blue-normal;
width: 24px; color: $blue-normal;
height: 24px;
&::before { &:hover,
top: 1px; &:focus,
left: 1px; &:active {
} background-color: rgba($blue-normal, 0.1);
border-color: $blue-normal;
} }
} }
.stage { &.ci-status-icon-canceled,
max-width: 100px; &.ci-status-icon-disabled,
width: 100px; &.ci-status-icon-not-found,
} &.ci-status-icon-manual {
border-color: $gl-text-color;
color: $gl-text-color;
.ci-status-icon svg { &:hover,
height: 18px; &:focus,
width: 18px; &:active {
background-color: rgba($gl-text-color, 0.1);
border-color: $gl-text-color;
}
} }
.ci-status-text { &.ci-status-icon-created,
max-width: 95px; &.ci-status-icon-skipped {
border-color: $gray-darkest;
color: $gray-darkest;
&:hover,
&:focus,
&:active {
background-color: rgba($gray-darkest, 0.1);
border-color: $gray-darkest;
}
} }
} }
/** // dropdown content for big and mini pipeline
* Builds dropdown in mini pipeline .big-pipeline-graph-dropdown-menu,
*/ .mini-pipeline-graph-dropdown-menu {
.mini-pipeline-graph { width: 195px;
.builds-dropdown { max-width: 195px;
background-color: transparent;
padding: 0;
color: $gl-text-color-secondary;
border: none;
margin: 0;
&:focus,
&:hover {
outline: none;
margin-right: -8px;
.ci-status-icon { li {
width: 32px; padding: 2px 3px;
padding: 0 8px 0 0; }
transition: width 0.1s cubic-bezier(0.25, 0, 1, 1);
+ .dropdown-caret { .scrollable-menu {
visibility: visible; max-height: 245px;
opacity: 1; overflow: auto;
} }
}
}
&:focus, // Loading icon
&:active { .builds-dropdown-loading {
.ci-status-icon-success { margin: 0 auto;
background-color: rgba($gl-success, .1); width: 20px;
} }
// Action icon on the right
a.ci-action-icon-wrapper {
color: $action-icon-color;
border: 1px solid $action-icon-color;
border-radius: 20px;
width: 22px;
height: 22px;
padding: 2px 0 0 5px;
cursor: pointer;
float: right;
margin: -26px 9px 0 0;
font-size: 12px;
background-color: $white-light;
.ci-status-icon-failed { &:hover,
background-color: rgba($gl-danger, .1); &:focus {
} text-decoration: none;
color: $gl-text-color;
background-color: $stage-hover-bg;
border: 1px solid transparent;
}
}
.ci-status-icon-pending, // link to the build
.ci-status-icon-success_with_warnings { .mini-pipeline-graph-dropdown-item {
background-color: rgba($gl-warning, .1); padding: 3px 7px 4px;
} clear: both;
font-weight: normal;
line-height: 1.428571429;
white-space: nowrap;
margin: 0 5px;
border-radius: 3px;
.ci-status-icon-running { // build name
background-color: rgba($blue-normal, .1); .ci-build-text {
} font-weight: 200;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 90px;
color: $gl-text-color-secondary;
margin-left: 2px;
display: inline-block;
top: 1px;
vertical-align: text-bottom;
position: relative;
}
.ci-status-icon-canceled, // status icon on the left
.ci-status-icon-disabled, .ci-status-icon {
.ci-status-icon-not-found { top: 3px;
background-color: rgba($gl-text-color, .1); position: relative;
}
.ci-status-icon-created, > svg {
.ci-status-icon-skipped { overflow: visible;
background-color: rgba($gray-darkest, .1); width: 18px;
height: 18px;
} }
} }
.mini-pipeline-graph-icon-container { &:hover,
.dropdown-caret { &:focus {
font-size: 11px; outline: none;
position: absolute; text-decoration: none;
top: 6px; color: $gl-text-color;
left: 20px; background-color: $stage-hover-bg;
margin-right: -6px;
z-index: 2;
visibility: hidden;
opacity: 0;
transition: visibility 0.1s, opacity 0.1s linear;
}
} }
} }
}
.dropdown-build .build-content { // Dropdown in the big pipeline graph
padding: 3px 7px 7px; .big-pipeline-graph-dropdown-menu {
} width: 195px;
min-width: 195px;
.builds-dropdown-loading { left: auto;
margin: 10px auto; right: -195px;
width: 18px; top: -4px;
} box-shadow: 0 1px 5px $black-transparent;
.grouped-pipeline-dropdown {
right: -172px;
top: 23px;
min-height: 50px;
a { .mini-pipeline-graph-dropdown-item {
color: $gl-text-color-secondary; .ci-status-icon {
top: -1px;
} }
} }
}
/**
* Top arrow in the dropdown in the mini pipeline graph
*/
.mini-pipeline-graph-dropdown-menu {
.arrow-up { .arrow-up {
&::before, &::before,
&::after { &::after {
...@@ -898,31 +907,8 @@ ...@@ -898,31 +907,8 @@
} }
/** /**
* Icons in mini pipeline graph * Terminal
*/ */
.mini-pipeline-graph-icon-container .ci-status-icon {
display: inline-block;
border: 1px solid;
border-radius: 22px;
margin-right: 1px;
width: 22px;
height: 22px;
position: relative;
z-index: 2;
transition: all 0.1s cubic-bezier(0.25, 0, 1, 1);
svg {
top: -1px;
left: -1px;
}
}
.stage-cell .mini-pipeline-graph-icon-container .ci-status-icon svg {
width: 22px;
height: 22px;
}
.terminal-icon { .terminal-icon {
margin-left: 3px; margin-left: 3px;
} }
......
-# Renders the content of each li in the dropdown
- subject = local_assigns.fetch(:subject)
- status = subject.detailed_status(current_user)
- klass = "ci-status-icon ci-status-icon-#{status.group}"
- tooltip = "#{subject.name} - #{status.label}"
- if status.has_details?
= link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item', data: { toggle: 'tooltip', title: tooltip } do
%span{ class: klass }= custom_icon(status.icon)
%span.ci-build-text= subject.name
- else
.mini-pipeline-graph-dropdown-item{ data: { toggle: 'tooltip', title: tooltip } }
%span{ class: klass }= custom_icon(status.icon)
%span.ci-build-text= subject.name
- if status.has_action?
= link_to status.action_path, class: 'ci-action-icon-wrapper js-ci-action-icon', method: status.action_method, data: { toggle: 'tooltip', title: status.action_title } do
= icon(status.action_icon, class: status.action_class)
...@@ -47,21 +47,18 @@ ...@@ -47,21 +47,18 @@
- icon_status = "#{detailed_status.icon}_borderless" - icon_status = "#{detailed_status.icon}_borderless"
- status_klass = "ci-status-icon ci-status-icon-#{detailed_status.group}" - status_klass = "ci-status-icon ci-status-icon-#{detailed_status.group}"
.stage-container.mini-pipeline-graph .stage-container.dropdown.js-mini-pipeline-graph
.dropdown.inline.build-content %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) } }
%button.has-tooltip.builds-dropdown.js-builds-dropdown-button{ 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)
%span.has-tooltip{ class: status_klass } = icon('caret-down')
%span.mini-pipeline-graph-icon-container
%span{ class: status_klass }= custom_icon(icon_status)
= icon('caret-down', class: 'dropdown-caret')
.js-builds-dropdown-container %ul.dropdown-menu.mini-pipeline-graph-dropdown-menu.js-builds-dropdown-container
.dropdown-menu.grouped-pipeline-dropdown .arrow-up
.arrow-up .js-builds-dropdown-list.scrollable-menu
.js-builds-dropdown-list
.js-builds-dropdown-loading.builds-dropdown-loading.hidden
%span.fa.fa-spinner.fa-spin
.js-builds-dropdown-loading.builds-dropdown-loading.hidden
%span.fa.fa-spinner.fa-spin
%td %td
- if pipeline.duration - if pipeline.duration
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
%div %div
.nothing-here-block No pipelines to show .nothing-here-block No pipelines to show
- else - else
.table-holder .table-holder.pipelines
%table.table.ci-table.js-pipeline-table %table.table.ci-table.js-pipeline-table
%thead %thead
%th.pipeline-status Status %th.pipeline-status Status
......
%ul - @stage.statuses.latest.each do |status|
- @stage.statuses.latest.each do |status| %li
%li.dropdown-build = render 'ci/status/dropdown_graph_badge', subject: status
= render 'ci/status/graph_badge', subject: status
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
%span.ci-status-text %span.ci-status-text
= name = name
%span.dropdown-counter-badge= subject.size %span.dropdown-counter-badge= subject.size
.dropdown-menu.grouped-pipeline-dropdown
%ul.dropdown-menu.big-pipeline-graph-dropdown-menu.js-grouped-pipeline-dropdown
.arrow .arrow
%ul .scrollable-menu
- subject.each do |status| - subject.each do |status|
%li.dropdown-build %li
= render 'ci/status/graph_badge', subject: status = render 'ci/status/dropdown_graph_badge', subject: status
---
title: Fixes and Improves CSS and HTML problems in mini pipeline graph and builds dropdown
merge_request: 8443
author:
...@@ -183,7 +183,7 @@ describe 'Pipelines', :feature, :js do ...@@ -183,7 +183,7 @@ describe 'Pipelines', :feature, :js do
it 'should render a mini pipeline graph' do it 'should render a mini pipeline graph' do
endpoint = stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: build.name) endpoint = stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: build.name)
expect(page).to have_selector('.mini-pipeline-graph') expect(page).to have_selector('.js-mini-pipeline-graph')
expect(page).to have_selector(".js-builds-dropdown-button[data-stage-endpoint='#{endpoint}']") expect(page).to have_selector(".js-builds-dropdown-button[data-stage-endpoint='#{endpoint}']")
end end
...@@ -201,7 +201,7 @@ describe 'Pipelines', :feature, :js do ...@@ -201,7 +201,7 @@ describe 'Pipelines', :feature, :js do
wait_for_ajax wait_for_ajax
find('a.ci-action-icon-container').trigger('click') find('a.js-ci-action-icon').trigger('click')
expect(page).not_to have_content('Cancel running') expect(page).not_to have_content('Cancel running')
end end
end end
......
...@@ -29,7 +29,7 @@ describe 'projects/pipelines/show' do ...@@ -29,7 +29,7 @@ describe 'projects/pipelines/show' do
render render
expect(rendered).to have_css('.js-pipeline-graph') expect(rendered).to have_css('.js-pipeline-graph')
expect(rendered).to have_css('.grouped-pipeline-dropdown') expect(rendered).to have_css('.js-grouped-pipeline-dropdown')
# stages # stages
expect(rendered).to have_text('Build') expect(rendered).to have_text('Build')
......
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