Merge branch '58105-pipeline-author-and-commit-author-too-close-together-in-pipeline-list' into 'master'

Improve pipelines table spacing, add triggerer column

Closes #38802 and #58105

See merge request gitlab-org/gitlab-ce!26136
This commit is contained in:
Filipa Lacerda 2019-05-06 11:16:28 +00:00
commit ef440879f1
9 changed files with 118 additions and 65 deletions

View File

@ -0,0 +1,35 @@
<script>
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
export default {
components: {
UserAvatarLink,
},
props: {
pipeline: {
type: Object,
required: true,
},
},
computed: {
user() {
return this.pipeline.user;
},
},
};
</script>
<template>
<div class="table-section section-10 d-none d-sm-none d-md-block pipeline-triggerer">
<user-avatar-link
v-if="user"
:link-href="user.path"
:img-src="user.avatar_url"
:img-size="26"
:tooltip-text="user.name"
class="prepend-left-default js-pipeline-url-user"
/>
<span v-else class="prepend-left-default js-pipeline-url-api api">
{{ s__('Pipelines|API') }}
</span>
</div>
</template>

View File

@ -59,19 +59,10 @@ export default {
};
</script>
<template>
<div class="table-section section-15 d-none d-sm-none d-md-block pipeline-tags">
<div class="table-section section-10 d-none d-sm-none d-md-block pipeline-tags">
<gl-link :href="pipeline.path" class="js-pipeline-url-link">
<span class="pipeline-id">#{{ pipeline.id }}</span>
</gl-link>
<span>by</span>
<user-avatar-link
v-if="user"
:link-href="user.path"
:img-src="user.avatar_url"
:tooltip-text="user.name"
class="js-pipeline-url-user"
/>
<span v-if="!user" class="js-pipeline-url-api api"> API </span>
<div class="label-container">
<span
v-if="pipeline.flags.latest"

View File

@ -1,4 +1,5 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
import PipelinesTableRowComponent from './pipelines_table_row.vue';
import PipelineStopModal from './pipeline_stop_modal.vue';
import eventHub from '../event_hub';
@ -13,6 +14,9 @@ export default {
PipelinesTableRowComponent,
PipelineStopModal,
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
pipelines: {
type: Array,
@ -62,16 +66,19 @@ export default {
<template>
<div class="ci-table">
<div class="gl-responsive-table-row table-row-header" role="row">
<div class="table-section section-10 js-pipeline-status pipeline-status" role="rowheader">
<div class="table-section section-10 js-pipeline-status" role="rowheader">
{{ s__('Pipeline|Status') }}
</div>
<div class="table-section section-15 js-pipeline-info pipeline-info" role="rowheader">
<div class="table-section section-10 js-pipeline-info pipeline-info" role="rowheader">
{{ s__('Pipeline|Pipeline') }}
</div>
<div class="table-section section-10 js-triggerer-info triggerer-info" role="rowheader">
{{ s__('Pipeline|Triggerer') }}
</div>
<div class="table-section section-20 js-pipeline-commit pipeline-commit" role="rowheader">
{{ s__('Pipeline|Commit') }}
</div>
<div class="table-section section-20 js-pipeline-stages pipeline-stages" role="rowheader">
<div class="table-section section-15 js-pipeline-stages pipeline-stages" role="rowheader">
{{ s__('Pipeline|Stages') }}
</div>
</div>

View File

@ -5,6 +5,7 @@ import PipelinesArtifactsComponent from './pipelines_artifacts.vue';
import CiBadge from '../../vue_shared/components/ci_badge_link.vue';
import PipelineStage from './stage.vue';
import PipelineUrl from './pipeline_url.vue';
import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelinesTimeago from './time_ago.vue';
import CommitComponent from '../../vue_shared/components/commit.vue';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
@ -23,6 +24,7 @@ export default {
CommitComponent,
PipelineStage,
PipelineUrl,
PipelineTriggerer,
CiBadge,
PipelinesTimeago,
LoadingButton,
@ -264,8 +266,9 @@ export default {
</div>
<pipeline-url :pipeline="pipeline" :auto-devops-help-path="autoDevopsHelpPath" />
<pipeline-triggerer :pipeline="pipeline" />
<div class="table-section section-20">
<div class="table-section section-wrap section-20">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Commit') }}</div>
<div class="table-mobile-content">
<commit-component
@ -281,7 +284,7 @@ export default {
</div>
</div>
<div class="table-section section-wrap section-20 stage-cell">
<div class="table-section section-wrap section-15 stage-cell">
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Stages') }}</div>
<div class="table-mobile-content">
<template v-if="pipeline.details.stages.length > 0">

View File

@ -0,0 +1,5 @@
---
title: Improve pipelines table spacing, add triggerer column
merge_request: 26136
author:
type: changed

View File

@ -6719,6 +6719,9 @@ msgstr ""
msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr ""
msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence"
msgstr ""
@ -6797,6 +6800,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
msgid "Pipeline|Variables"
msgstr ""

View File

@ -0,0 +1,54 @@
import { mount } from '@vue/test-utils';
import pipelineTriggerer from '~/pipelines/components/pipeline_triggerer.vue';
describe('Pipelines Triggerer', () => {
let wrapper;
const mockData = {
pipeline: {
user: {
name: 'foo',
avatar_url: '/avatar',
path: '/path',
},
},
};
const createComponent = () => {
wrapper = mount(pipelineTriggerer, {
propsData: mockData,
});
};
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('should render a table cell', () => {
expect(wrapper.contains('.table-section')).toBe(true);
});
it('should render triggerer information when triggerer is provided', () => {
const link = wrapper.find('.js-pipeline-url-user');
expect(link.attributes('href')).toEqual(mockData.pipeline.user.path);
expect(link.find('.js-user-avatar-image-toolip').text()).toEqual(mockData.pipeline.user.name);
expect(link.find('img.avatar').attributes('src')).toEqual(
`${mockData.pipeline.user.avatar_url}?width=26`,
);
});
it('should render "API" when no triggerer is provided', () => {
wrapper.setProps({
pipeline: {
user: null,
},
});
expect(wrapper.find('.js-pipeline-url-api').text()).toEqual('API');
});
});

View File

@ -42,54 +42,6 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1');
});
it('should render user information when a user is provided', () => {
const mockData = {
pipeline: {
id: 1,
path: 'foo',
flags: {},
user: {
web_url: '/',
name: 'foo',
avatar_url: '/',
path: '/',
},
},
autoDevopsHelpPath: 'foo',
};
const component = new PipelineUrlComponent({
propsData: mockData,
}).$mount();
const image = component.$el.querySelector('.js-pipeline-url-user img');
const tooltip = component.$el.querySelector(
'.js-pipeline-url-user .js-user-avatar-image-toolip',
);
expect(component.$el.querySelector('.js-pipeline-url-user').getAttribute('href')).toEqual(
mockData.pipeline.user.web_url,
);
expect(tooltip.textContent.trim()).toEqual(mockData.pipeline.user.name);
expect(image.getAttribute('src')).toEqual(`${mockData.pipeline.user.avatar_url}?width=20`);
});
it('should render "API" when no user is provided', () => {
const component = new PipelineUrlComponent({
propsData: {
pipeline: {
id: 1,
path: 'foo',
flags: {},
},
autoDevopsHelpPath: 'foo',
},
}).$mount();
expect(component.$el.querySelector('.js-pipeline-url-api').textContent).toContain('API');
});
it('should render latest, yaml invalid, merge request, and stuck flags when provided', () => {
const component = new PipelineUrlComponent({
propsData: {

View File

@ -80,13 +80,13 @@ describe('Pipelines Table Row', () => {
it('should render user information', () => {
expect(
component.$el
.querySelector('.table-section:nth-child(2) a:nth-child(3)')
.querySelector('.table-section:nth-child(3) .js-pipeline-url-user')
.getAttribute('href'),
).toEqual(pipeline.user.path);
expect(
component.$el
.querySelector('.table-section:nth-child(2) .js-user-avatar-image-toolip')
.querySelector('.table-section:nth-child(3) .js-user-avatar-image-toolip')
.textContent.trim(),
).toEqual(pipeline.user.name);
});