Commit ef440879 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch...

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
parents 02ca1577 a6585cac
<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>
...@@ -59,19 +59,10 @@ export default { ...@@ -59,19 +59,10 @@ export default {
}; };
</script> </script>
<template> <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"> <gl-link :href="pipeline.path" class="js-pipeline-url-link">
<span class="pipeline-id">#{{ pipeline.id }}</span> <span class="pipeline-id">#{{ pipeline.id }}</span>
</gl-link> </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"> <div class="label-container">
<span <span
v-if="pipeline.flags.latest" v-if="pipeline.flags.latest"
......
<script> <script>
import { GlTooltipDirective } from '@gitlab/ui';
import PipelinesTableRowComponent from './pipelines_table_row.vue'; import PipelinesTableRowComponent from './pipelines_table_row.vue';
import PipelineStopModal from './pipeline_stop_modal.vue'; import PipelineStopModal from './pipeline_stop_modal.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
...@@ -13,6 +14,9 @@ export default { ...@@ -13,6 +14,9 @@ export default {
PipelinesTableRowComponent, PipelinesTableRowComponent,
PipelineStopModal, PipelineStopModal,
}, },
directives: {
GlTooltip: GlTooltipDirective,
},
props: { props: {
pipelines: { pipelines: {
type: Array, type: Array,
...@@ -62,16 +66,19 @@ export default { ...@@ -62,16 +66,19 @@ export default {
<template> <template>
<div class="ci-table"> <div class="ci-table">
<div class="gl-responsive-table-row table-row-header" role="row"> <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') }} {{ s__('Pipeline|Status') }}
</div> </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') }} {{ s__('Pipeline|Pipeline') }}
</div> </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"> <div class="table-section section-20 js-pipeline-commit pipeline-commit" role="rowheader">
{{ s__('Pipeline|Commit') }} {{ s__('Pipeline|Commit') }}
</div> </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') }} {{ s__('Pipeline|Stages') }}
</div> </div>
</div> </div>
......
...@@ -5,6 +5,7 @@ import PipelinesArtifactsComponent from './pipelines_artifacts.vue'; ...@@ -5,6 +5,7 @@ import PipelinesArtifactsComponent from './pipelines_artifacts.vue';
import CiBadge from '../../vue_shared/components/ci_badge_link.vue'; import CiBadge from '../../vue_shared/components/ci_badge_link.vue';
import PipelineStage from './stage.vue'; import PipelineStage from './stage.vue';
import PipelineUrl from './pipeline_url.vue'; import PipelineUrl from './pipeline_url.vue';
import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelinesTimeago from './time_ago.vue'; import PipelinesTimeago from './time_ago.vue';
import CommitComponent from '../../vue_shared/components/commit.vue'; import CommitComponent from '../../vue_shared/components/commit.vue';
import LoadingButton from '../../vue_shared/components/loading_button.vue'; import LoadingButton from '../../vue_shared/components/loading_button.vue';
...@@ -23,6 +24,7 @@ export default { ...@@ -23,6 +24,7 @@ export default {
CommitComponent, CommitComponent,
PipelineStage, PipelineStage,
PipelineUrl, PipelineUrl,
PipelineTriggerer,
CiBadge, CiBadge,
PipelinesTimeago, PipelinesTimeago,
LoadingButton, LoadingButton,
...@@ -264,8 +266,9 @@ export default { ...@@ -264,8 +266,9 @@ export default {
</div> </div>
<pipeline-url :pipeline="pipeline" :auto-devops-help-path="autoDevopsHelpPath" /> <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-header" role="rowheader">{{ s__('Pipeline|Commit') }}</div>
<div class="table-mobile-content"> <div class="table-mobile-content">
<commit-component <commit-component
...@@ -281,7 +284,7 @@ export default { ...@@ -281,7 +284,7 @@ export default {
</div> </div>
</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-header" role="rowheader">{{ s__('Pipeline|Stages') }}</div>
<div class="table-mobile-content"> <div class="table-mobile-content">
<template v-if="pipeline.details.stages.length > 0"> <template v-if="pipeline.details.stages.length > 0">
......
---
title: Improve pipelines table spacing, add triggerer column
merge_request: 26136
author:
type: changed
...@@ -6719,6 +6719,9 @@ msgstr "" ...@@ -6719,6 +6719,9 @@ msgstr ""
msgid "Pipelines settings for '%{project_name}' were successfully updated." msgid "Pipelines settings for '%{project_name}' were successfully updated."
msgstr "" msgstr ""
msgid "Pipelines|API"
msgstr ""
msgid "Pipelines|Build with confidence" msgid "Pipelines|Build with confidence"
msgstr "" msgstr ""
...@@ -6797,6 +6800,9 @@ msgstr "" ...@@ -6797,6 +6800,9 @@ msgstr ""
msgid "Pipeline|Stop pipeline #%{pipelineId}?" msgid "Pipeline|Stop pipeline #%{pipelineId}?"
msgstr "" msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
msgid "Pipeline|Variables" msgid "Pipeline|Variables"
msgstr "" msgstr ""
......
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');
});
});
...@@ -42,54 +42,6 @@ describe('Pipeline Url Component', () => { ...@@ -42,54 +42,6 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1'); 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', () => { it('should render latest, yaml invalid, merge request, and stuck flags when provided', () => {
const component = new PipelineUrlComponent({ const component = new PipelineUrlComponent({
propsData: { propsData: {
......
...@@ -80,13 +80,13 @@ describe('Pipelines Table Row', () => { ...@@ -80,13 +80,13 @@ describe('Pipelines Table Row', () => {
it('should render user information', () => { it('should render user information', () => {
expect( expect(
component.$el component.$el
.querySelector('.table-section:nth-child(2) a:nth-child(3)') .querySelector('.table-section:nth-child(3) .js-pipeline-url-user')
.getAttribute('href'), .getAttribute('href'),
).toEqual(pipeline.user.path); ).toEqual(pipeline.user.path);
expect( expect(
component.$el 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(), .textContent.trim(),
).toEqual(pipeline.user.name); ).toEqual(pipeline.user.name);
}); });
......
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