Creates vue components for stage dropdowns and job list container for job log view
This commit is contained in:
parent
cf2c99cc0a
commit
da9b3b3d0f
6 changed files with 355 additions and 0 deletions
60
app/assets/javascripts/jobs/components/jobs_container.vue
Normal file
60
app/assets/javascripts/jobs/components/jobs_container.vue
Normal file
|
@ -0,0 +1,60 @@
|
|||
<script>
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
},
|
||||
directives: {
|
||||
tooltip,
|
||||
},
|
||||
props: {
|
||||
jobs: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="builds-container">
|
||||
<div
|
||||
class="build-job"
|
||||
>
|
||||
<a
|
||||
v-tooltip
|
||||
v-for="job in jobs"
|
||||
:key="job.id"
|
||||
:href="job.path"
|
||||
:title="job.tooltip"
|
||||
:class="{ active: job.active, retried: job.retried }"
|
||||
>
|
||||
<icon
|
||||
v-if="job.active"
|
||||
name="arrow-right"
|
||||
class="js-arrow-right"
|
||||
/>
|
||||
|
||||
<ci-icon :status="job.status" />
|
||||
|
||||
<span>
|
||||
<template v-if="job.name">
|
||||
{{ job.name }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ job.id }}
|
||||
</template>
|
||||
</span>
|
||||
|
||||
<icon
|
||||
v-if="job.retried"
|
||||
name="retry"
|
||||
class="js-retry-icon"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
97
app/assets/javascripts/jobs/components/stages_dropdown.vue
Normal file
97
app/assets/javascripts/jobs/components/stages_dropdown.vue
Normal file
|
@ -0,0 +1,97 @@
|
|||
<script>
|
||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
|
||||
import { sprintf, __ } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CiIcon,
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
pipelineId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
pipelinePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
pipelineRef: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
pipelineRefPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
stages: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
pipelineStatus: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedStage: this.stages.length > 0 ? this.stages[0].name : __('More'),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
pipelineLink() {
|
||||
return sprintf(__('Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}'), {
|
||||
pipelineLinkStart: `<a href=${this.pipelinePath} class="js-pipeline-path link-commit">`,
|
||||
pipelineId: this.pipelineId,
|
||||
pipelineLinkEnd: '</a>',
|
||||
pipelineLinkRefStart: `<a href=${this.pipelineRefPath} class="link-commit ref-name">`,
|
||||
pipelineRef: this.pipelineRef,
|
||||
pipelineLinkRefEnd: '</a>',
|
||||
}, false);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onStageClick(stage) {
|
||||
// todo: consider moving into store
|
||||
this.selectedStage = stage.name;
|
||||
|
||||
// update dropdown with jobs
|
||||
// jobs container is a new component.
|
||||
this.$emit('requestSidebarStageDropdown', stage);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="block-last">
|
||||
<ci-icon :status="pipelineStatus" />
|
||||
|
||||
<p v-html="pipelineLink"></p>
|
||||
|
||||
<div class="dropdown">
|
||||
<button
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
>
|
||||
{{ selectedStage }}
|
||||
<icon name="chevron-down" />
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li
|
||||
v-for="(stage, index) in stages"
|
||||
:key="index"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="stage-item"
|
||||
@click="onStageClick(stage)"
|
||||
>
|
||||
{{ stage.name }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
6
changelogs/unreleased/50101-builds-dropdown.yml
Normal file
6
changelogs/unreleased/50101-builds-dropdown.yml
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Creates vue components for stage dropdowns and job list container for job log
|
||||
view
|
||||
merge_request:
|
||||
author:
|
||||
type: other
|
|
@ -4110,6 +4110,9 @@ msgstr ""
|
|||
msgid "Pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pipeline Health"
|
||||
msgstr ""
|
||||
|
||||
|
|
126
spec/javascripts/jobs/jobs_container_spec.js
Normal file
126
spec/javascripts/jobs/jobs_container_spec.js
Normal file
|
@ -0,0 +1,126 @@
|
|||
import Vue from 'vue';
|
||||
import component from '~/jobs/components/jobs_container.vue';
|
||||
import mountComponent from '../helpers/vue_mount_component_helper';
|
||||
|
||||
describe('Artifacts block', () => {
|
||||
const Component = Vue.extend(component);
|
||||
let vm;
|
||||
|
||||
const retried = {
|
||||
status: {
|
||||
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
|
||||
group: 'success',
|
||||
has_details: true,
|
||||
icon: 'status_success',
|
||||
label: 'passed',
|
||||
text: 'passed',
|
||||
tooltip: 'passed',
|
||||
},
|
||||
path: 'job/233432756',
|
||||
id: '233432756',
|
||||
tooltip: 'build - passed',
|
||||
retried: true,
|
||||
};
|
||||
|
||||
const active = {
|
||||
name: 'test',
|
||||
status: {
|
||||
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
|
||||
group: 'success',
|
||||
has_details: true,
|
||||
icon: 'status_success',
|
||||
label: 'passed',
|
||||
text: 'passed',
|
||||
tooltip: 'passed',
|
||||
},
|
||||
path: 'job/2322756',
|
||||
id: '2322756',
|
||||
tooltip: 'build - passed',
|
||||
active: true,
|
||||
};
|
||||
|
||||
const job = {
|
||||
name: 'build',
|
||||
status: {
|
||||
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
|
||||
group: 'success',
|
||||
has_details: true,
|
||||
icon: 'status_success',
|
||||
label: 'passed',
|
||||
text: 'passed',
|
||||
tooltip: 'passed',
|
||||
},
|
||||
path: 'job/232153',
|
||||
id: '232153',
|
||||
tooltip: 'build - passed',
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
it('renders list of jobs', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [job, retried, active],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelectorAll('a').length).toEqual(3);
|
||||
});
|
||||
|
||||
it('renders arrow right when job is active', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [active],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('a .js-arrow-right')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('does not render arrow right when job is not active', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [job],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('a .js-arrow-right')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders job name when present', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [job],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('a').textContent.trim()).toContain(job.name);
|
||||
expect(vm.$el.querySelector('a').textContent.trim()).not.toContain(job.id);
|
||||
});
|
||||
|
||||
it('renders job id when job name is not available', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [retried],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('a').textContent.trim()).toContain(retried.id);
|
||||
});
|
||||
|
||||
it('links to the job page', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [job],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(job.path);
|
||||
});
|
||||
|
||||
it('renders retry icon when job was retried', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [retried],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('.js-retry-icon')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('does not render retry icon when job was not retried', () => {
|
||||
vm = mountComponent(Component, {
|
||||
jobs: [job],
|
||||
});
|
||||
|
||||
expect(vm.$el.querySelector('.js-retry-icon')).toBeNull();
|
||||
});
|
||||
});
|
63
spec/javascripts/jobs/stages_dropdown_spec.js
Normal file
63
spec/javascripts/jobs/stages_dropdown_spec.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
import Vue from 'vue';
|
||||
import component from '~/jobs/components/stages_dropdown.vue';
|
||||
import mountComponent from '../helpers/vue_mount_component_helper';
|
||||
|
||||
describe('Artifacts block', () => {
|
||||
const Component = Vue.extend(component);
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
vm = mountComponent(Component, {
|
||||
pipelineId: 28029444,
|
||||
pipelinePath: 'pipeline/28029444',
|
||||
pipelineRef: '50101-truncated-job-information',
|
||||
pipelineRefPath: 'commits/50101-truncated-job-information',
|
||||
stages: [
|
||||
{
|
||||
name: 'build',
|
||||
},
|
||||
{
|
||||
name: 'test',
|
||||
},
|
||||
],
|
||||
pipelineStatus: {
|
||||
details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
|
||||
group: 'success',
|
||||
has_details: true,
|
||||
icon: 'status_success',
|
||||
label: 'passed',
|
||||
text: 'passed',
|
||||
tooltip: 'passed',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
});
|
||||
|
||||
it('renders pipeline status', () => {
|
||||
expect(vm.$el.querySelector('.js-ci-status-icon-success')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders pipeline link', () => {
|
||||
expect(vm.$el.querySelector('.js-pipeline-path').getAttribute('href')).toEqual(
|
||||
'pipeline/28029444',
|
||||
);
|
||||
});
|
||||
|
||||
it('renders dropdown with stages', () => {
|
||||
expect(vm.$el.querySelector('.dropdown button').textContent).toContain('build');
|
||||
});
|
||||
|
||||
it('updates selected stage on click', done => {
|
||||
vm.$el.querySelectorAll('.stage-item')[1].click();
|
||||
vm
|
||||
.$nextTick()
|
||||
.then(() => {
|
||||
expect(vm.$el.querySelector('.dropdown button').textContent).toContain('test');
|
||||
})
|
||||
.then(done)
|
||||
.catch(done.fail);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue