diff options
5 files changed, 114 insertions, 4 deletions
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index a84161ef5e7..1f1b99ff401 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -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> diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue index b7da185e280..9b1bbb0906f 100644 --- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue @@ -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> diff --git a/app/assets/javascripts/vue_shared/ci_action_icons.js b/app/assets/javascripts/vue_shared/ci_action_icons.js index 734b3c6c45e..ee41dc95beb 100644 --- a/app/assets/javascripts/vue_shared/ci_action_icons.js +++ b/app/assets/javascripts/vue_shared/ci_action_icons.js @@ -1,6 +1,7 @@ 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 = ''; } diff --git a/spec/javascripts/pipelines/graph/graph_component_spec.js b/spec/javascripts/pipelines/graph/graph_component_spec.js index a756617e65e..77f42312b40 100644 --- a/spec/javascripts/pipelines/graph/graph_component_spec.js +++ b/spec/javascripts/pipelines/graph/graph_component_spec.js @@ -52,6 +52,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', + }, + }, + }], + }], }], }, }), { @@ -73,6 +123,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(); diff --git a/spec/javascripts/vue_shared/ci_action_icons_spec.js b/spec/javascripts/vue_shared/ci_action_icons_spec.js index 2e89a07e76e..3d53a5ab24d 100644 --- a/spec/javascripts/vue_shared/ci_action_icons_spec.js +++ b/spec/javascripts/vue_shared/ci_action_icons_spec.js @@ -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); + }); }); |