Commit b2fc6326 authored by Fatih Acet's avatar Fatih Acet

Merge branch '31053-pipeline-ux' into 'master'

Adds left connector class to the rendered graph

Closes #31053

See merge request !11179
parents a353c966 0c3abe3e
......@@ -64,6 +64,24 @@
capitalizeStageName(name) {
return name.charAt(0).toUpperCase() + name.slice(1);
},
isFirstColumn(index) {
return index === 0;
},
stageConnectorClass(index, stage) {
let className;
// If it's the first stage column and only has one job
if (index === 0 && stage.groups.length === 1) {
className = 'no-margin';
} else if (index > 0) {
// If it is not the first column
className = 'left-margin';
}
return className;
},
},
};
</script>
......@@ -82,10 +100,12 @@
v-if="!isLoading"
class="stage-column-list">
<stage-column-component
v-for="stage in state.graph"
v-for="(stage, index) in state.graph"
:title="capitalizeStageName(stage.name)"
:jobs="stage.groups"
:key="stage.name"/>
:key="stage.name"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"/>
</ul>
</div>
</div>
......
......@@ -13,6 +13,18 @@ export default {
type: Array,
required: true,
},
isFirstColumn: {
type: Boolean,
required: false,
default: false,
},
stageConnectorClass: {
type: String,
required: false,
default: '',
},
},
components: {
......@@ -28,20 +40,27 @@ export default {
jobId(job) {
return `ci-badge-${job.name}`;
},
buildConnnectorClass(index) {
return index === 0 && !this.isFirstColumn ? 'left-connector' : '';
},
},
};
</script>
<template>
<li class="stage-column">
<li
class="stage-column"
:class="stageConnectorClass">
<div class="stage-name">
{{title}}
</div>
<div class="builds-container">
<ul>
<li
v-for="job in jobs"
v-for="(job, index) in jobs"
:key="job.id"
class="build"
:class="buildConnnectorClass(index)"
:id="jobId(job)">
<div class="curve"></div>
......
import cancelSVG from 'icons/_icon_action_cancel.svg';
import retrySVG from 'icons/_icon_action_retry.svg';
import playSVG from 'icons/_icon_action_play.svg';
import stopSVG from 'icons/_icon_action_stop.svg';
export default function getActionIcon(action) {
let icon;
......@@ -14,6 +15,9 @@ export default function getActionIcon(action) {
case 'icon_action_play':
icon = playSVG;
break;
case 'icon_action_stop':
icon = stopSVG;
break;
default:
icon = '';
}
......
......@@ -66,6 +66,56 @@ describe('graph component', () => {
},
},
}],
},
{
name: 'test_1',
title: 'test_1: passed',
status: {
icon: 'icon_status_success',
text: 'passed',
label: 'passed',
details_path: '/root/ci-mock/pipelines/123#test',
},
path: '/root/ci-mock/pipelines/123#test',
groups: [{
name: 'test',
size: 1,
jobs: [{
id: 4153,
name: 'test',
status: {
icon: 'icon_status_success',
text: 'passed',
label: 'passed',
details_path: '/root/ci-mock/builds/4153',
action: {
icon: 'icon_action_retry',
title: 'Retry',
path: '/root/ci-mock/builds/4153/retry',
method: 'post',
},
},
}],
}, {
name: 'test',
size: 1,
jobs: [{
id: 4153,
name: 'test',
status: {
icon: 'icon_status_success',
text: 'passed',
label: 'passed',
details_path: '/root/ci-mock/builds/4153',
action: {
icon: 'icon_action_retry',
title: 'Retry',
path: '/root/ci-mock/builds/4153/retry',
method: 'post',
},
},
}],
}],
}],
}],
},
......@@ -91,6 +141,18 @@ describe('graph component', () => {
setTimeout(() => {
expect(component.$el.classList.contains('js-pipeline-graph')).toEqual(true);
expect(
component.$el.querySelector('.stage-column:first-child').classList.contains('no-margin'),
).toEqual(true);
expect(
component.$el.querySelector('.stage-column:nth-child(2)').classList.contains('left-margin'),
).toEqual(true);
expect(
component.$el.querySelector('.stage-column:nth-child(2) .build:nth-child(1)').classList.contains('left-connector'),
).toEqual(true);
expect(component.$el.querySelector('loading-icon')).toBe(null);
expect(component.$el.querySelector('.stage-column-list')).toBeDefined();
......
......@@ -2,6 +2,7 @@ import getActionIcon from '~/vue_shared/ci_action_icons';
import cancelSVG from 'icons/_icon_action_cancel.svg';
import retrySVG from 'icons/_icon_action_retry.svg';
import playSVG from 'icons/_icon_action_play.svg';
import stopSVG from 'icons/_icon_action_stop.svg';
describe('getActionIcon', () => {
it('should return an empty string', () => {
......@@ -19,4 +20,8 @@ describe('getActionIcon', () => {
it('should return play svg', () => {
expect(getActionIcon('icon_action_play')).toEqual(playSVG);
});
it('should render stop svg', () => {
expect(getActionIcon('icon_action_stop')).toEqual(stopSVG);
});
});
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