diff options
7 files changed, 202 insertions, 17 deletions
diff --git a/app/assets/javascripts/pages/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/pages/projects/tree/components/commit_pipeline_status_component.vue new file mode 100644 index 00000000000..2bd1e8e3266 --- /dev/null +++ b/app/assets/javascripts/pages/projects/tree/components/commit_pipeline_status_component.vue @@ -0,0 +1,95 @@ +<script> + import Visibility from 'visibilityjs'; + import ciIcon from '~/vue_shared/components/ci_icon.vue'; + import Poll from '~/lib/utils/poll'; + import Flash from '~/flash'; + import tooltip from '~/vue_shared/directives/tooltip'; + import CommitPipelineService from '../services/commit_pipeline_service'; + + export default { + directives: { + tooltip, + }, + components: { + ciIcon, + }, + props: { + endpoint: { + type: String, + required: true, + }, + }, + data() { + return { + ciStatus: {}, + isLoading: true, + service: {}, + }; + }, + mounted() { + this.service = new CommitPipelineService(this.endpoint); + this.initPolling(); + }, + methods: { + successCallback(res) { + if (res.data.pipelines.length > 0) { + this.ciStatus = res.data.pipelines[0].details.status; + this.isLoading = false; + } else { + this.isLoading = true; + } + }, + errorCallback(err) { + Flash(err); + }, + initPolling() { + this.poll = new Poll({ + resource: this.service, + method: 'fetchData', + successCallback: response => this.successCallback(response), + errorCallback: this.errorCallback, + }); + + if (!Visibility.hidden()) { + this.isLoading = true; + this.poll.makeRequest(); + } else { + this.fetchPipelineCommitData(); + } + + Visibility.change(() => { + if (!Visibility.hidden()) { + this.poll.restart(); + } else { + this.poll.stop(); + } + }); + }, + fetchPipelineCommitData() { + this.service.fetchData() + .then(this.successCallback) + .catch(this.errorCallback); + }, + }, + destroy() { + this.poll.stop(); + }, + }; +</script> +<template> + <div + v-if="isLoading"> + </div> + <a + v-else + :href="ciStatus.details_path" + > + <ci-icon + v-tooltip + :title="ciStatus.text" + :aria-label="ciStatus.text" + data-container="body" + :status="ciStatus" + /> + </a> +</template> diff --git a/app/assets/javascripts/pages/projects/tree/services/commit_pipeline_service.js b/app/assets/javascripts/pages/projects/tree/services/commit_pipeline_service.js new file mode 100644 index 00000000000..4b4189bc2de --- /dev/null +++ b/app/assets/javascripts/pages/projects/tree/services/commit_pipeline_service.js @@ -0,0 +1,11 @@ +import axios from '~/lib/utils/axios_utils'; + +export default class CommitPipelineService { + constructor(endpoint) { + this.endpoint = endpoint; + } + + fetchData() { + return axios.get(this.endpoint); + } +} diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js index 28a0160f47d..7181d4dfd47 100644 --- a/app/assets/javascripts/pages/projects/tree/show/index.js +++ b/app/assets/javascripts/pages/projects/tree/show/index.js @@ -1,8 +1,10 @@ +import Vue from 'vue'; import TreeView from '../../../../tree'; import ShortcutsNavigation from '../../../../shortcuts_navigation'; import BlobViewer from '../../../../blob/viewer'; import NewCommitForm from '../../../../new_commit_form'; import { ajaxGet } from '../../../../lib/utils/common_utils'; +import commitPipelineStatus from '../components/commit_pipeline_status_component.vue'; export default () => { new ShortcutsNavigation(); // eslint-disable-line no-new @@ -11,5 +13,21 @@ export default () => { new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new $('#tree-slider').waitForImages(() => ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath)); + + const commitPipelineStatusEl = document.getElementById('commit-pipeline-status'); + // eslint-disable-next-line no-new + new Vue({ + el: '#commit-pipeline-status', + components: { + commitPipelineStatus, + }, + render(createElement) { + return createElement('commit-pipeline-status', { + props: { + endpoint: commitPipelineStatusEl.dataset.endpoint, + }, + }); + }, + }); }; diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index aeaa33bd3bd..adfd72556b8 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -195,6 +195,10 @@ .commit-actions { @media (min-width: $screen-sm-min) { font-size: 0; + + span { + font-size: 6px; + } } .ci-status-link { @@ -219,6 +223,11 @@ font-size: 14px; font-weight: $gl-font-weight-bold; } + + .ci-status-icon { + position: relative; + top: 3px; + } } .commit, diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index 636316da80a..e8365f1da1e 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -103,17 +103,6 @@ module CiStatusHelper tooltip_placement: tooltip_placement) end - def render_commit_status(commit, ref: nil, tooltip_placement: 'auto left') - project = commit.project - path = pipelines_project_commit_path(project, commit) - - render_status_with_link( - 'commit', - commit.status(ref), - path, - tooltip_placement: tooltip_placement) - end - def render_pipeline_status(pipeline, tooltip_placement: 'auto left') project = pipeline.project path = project_pipeline_path(project, pipeline) diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index d66066a6d0b..436e1739180 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -26,9 +26,6 @@ %span.commit-row-message.visible-xs-inline · = commit.short_id - - if commit.status(ref) - .visible-xs-inline - = render_commit_status(commit, ref: ref) - if commit.description? %button.text-expander.hidden-xs.js-toggle-button{ type: "button" } ... @@ -48,9 +45,7 @@ - else = render partial: 'projects/commit/ajax_signature', locals: { commit: commit } - - if commit.status(ref) - = render_commit_status(commit, ref: ref) - + #commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id) } } = link_to commit.short_id, link, class: "commit-sha btn btn-transparent btn-link" = clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard")) = link_to_browse_code(project, commit) diff --git a/spec/javascripts/commit/commit_pipeline_status_component_spec.js b/spec/javascripts/commit/commit_pipeline_status_component_spec.js new file mode 100644 index 00000000000..f6fca9e97e5 --- /dev/null +++ b/spec/javascripts/commit/commit_pipeline_status_component_spec.js @@ -0,0 +1,68 @@ +import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import commitPipelineStatus from '~/pages/projects/tree/components/commit_pipeline_status_component.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('Commit pipeline status component', () => { + let vm; + let component; + let mock; + const mockCiStatus = { + details_path: '/root/hello-world/pipelines/1', + favicon: 'canceled.ico', + group: 'canceled', + has_details: true, + icon: 'status_canceled', + label: 'canceled', + text: 'canceled', + }; + + beforeEach(() => { + mock = new MockAdapter(axios); + mock.onGet('/dummy/endpoint').reply(() => { + const res = Promise.resolve([200, { + pipelines: [ + { + details: { + status: mockCiStatus, + }, + }, + ], + }]); + return res; + }); + component = Vue.extend(commitPipelineStatus); + }); + + afterEach(() => { + mock.reset(); + }); + + describe('While polling pipeline data', () => { + beforeEach(() => { + vm = mountComponent(component, { + endpoint: '/dummy/endpoint', + }); + }); + + afterEach(() => { + vm.poll.stop(); + vm.$destroy(); + }); + + it('contains a ciStatus when the polling is succesful ', (done) => { + setTimeout(() => { + expect(vm.ciStatus).toEqual(mockCiStatus); + done(); + }, 1000); + }); + + it('contains a ci-status icon when polling is succesful', (done) => { + setTimeout(() => { + expect(vm.$el.querySelector('.ci-status-icon')).not.toBe(null); + done(); + }); + }); + }); +}); |