2017-08-17 22:00:37 +05:30
|
|
|
<script>
|
2018-10-15 14:42:47 +05:30
|
|
|
/**
|
|
|
|
* Renders each stage of the pipeline mini graph.
|
|
|
|
*
|
|
|
|
* Given the provided endpoint will make a request to
|
|
|
|
* fetch the dropdown data when the stage is clicked.
|
|
|
|
*
|
|
|
|
* Request is made inside this component to make it reusable between:
|
|
|
|
* 1. Pipelines main table
|
|
|
|
* 2. Pipelines table in commit and Merge request views
|
|
|
|
* 3. Merge request widget
|
|
|
|
* 4. Commit widget
|
|
|
|
*/
|
|
|
|
|
|
|
|
import $ from 'jquery';
|
2019-02-15 15:39:39 +05:30
|
|
|
import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
|
2018-10-15 14:42:47 +05:30
|
|
|
import { __ } from '../../locale';
|
|
|
|
import Flash from '../../flash';
|
|
|
|
import axios from '../../lib/utils/axios_utils';
|
|
|
|
import eventHub from '../event_hub';
|
|
|
|
import Icon from '../../vue_shared/components/icon.vue';
|
2018-12-13 13:39:08 +05:30
|
|
|
import JobItem from './graph/job_item.vue';
|
2018-10-15 14:42:47 +05:30
|
|
|
import { PIPELINES_TABLE } from '../constants';
|
|
|
|
|
|
|
|
export default {
|
|
|
|
components: {
|
|
|
|
Icon,
|
2018-12-13 13:39:08 +05:30
|
|
|
JobItem,
|
|
|
|
GlLoadingIcon,
|
2018-10-15 14:42:47 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
directives: {
|
2019-02-15 15:39:39 +05:30
|
|
|
GlTooltip: GlTooltipDirective,
|
2018-10-15 14:42:47 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
props: {
|
|
|
|
stage: {
|
|
|
|
type: Object,
|
|
|
|
required: true,
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
updateDropdown: {
|
|
|
|
type: Boolean,
|
|
|
|
required: false,
|
|
|
|
default: false,
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
type: {
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
default: '',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
isLoading: false,
|
|
|
|
dropdownContent: '',
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
computed: {
|
|
|
|
dropdownClass() {
|
|
|
|
return this.dropdownContent.length > 0
|
|
|
|
? 'js-builds-dropdown-container'
|
|
|
|
: 'js-builds-dropdown-loading';
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
triggerButtonClass() {
|
|
|
|
return `ci-status-icon-${this.stage.status.group}`;
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
borderlessIcon() {
|
|
|
|
return `${this.stage.status.icon}_borderless`;
|
|
|
|
},
|
|
|
|
},
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
watch: {
|
|
|
|
updateDropdown() {
|
|
|
|
if (this.updateDropdown && this.isDropdownOpen() && !this.isLoading) {
|
|
|
|
this.fetchJobs();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
updated() {
|
|
|
|
if (this.dropdownContent.length > 0) {
|
|
|
|
this.stopDropdownClickPropagation();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
onClickStage() {
|
|
|
|
if (!this.isDropdownOpen()) {
|
|
|
|
eventHub.$emit('clickedDropdown');
|
|
|
|
this.isLoading = true;
|
|
|
|
this.fetchJobs();
|
|
|
|
}
|
|
|
|
},
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
fetchJobs() {
|
|
|
|
axios
|
|
|
|
.get(this.stage.dropdown_path)
|
|
|
|
.then(({ data }) => {
|
|
|
|
this.dropdownContent = data.latest_statuses;
|
|
|
|
this.isLoading = false;
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
this.closeDropdown();
|
|
|
|
this.isLoading = false;
|
|
|
|
|
|
|
|
Flash(__('Something went wrong on our end.'));
|
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
/**
|
|
|
|
* When the user right clicks or cmd/ctrl + click in the job name
|
|
|
|
* the dropdown should not be closed and the link should open in another tab,
|
|
|
|
* so we stop propagation of the click event inside the dropdown.
|
|
|
|
*
|
|
|
|
* Since this component is rendered multiple times per page we need to guarantee we only
|
|
|
|
* target the click event of this component.
|
|
|
|
*/
|
|
|
|
stopDropdownClickPropagation() {
|
|
|
|
$(
|
|
|
|
'.js-builds-dropdown-list button, .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item',
|
|
|
|
this.$el,
|
|
|
|
).on('click', e => {
|
|
|
|
e.stopPropagation();
|
|
|
|
});
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
closeDropdown() {
|
|
|
|
if (this.isDropdownOpen()) {
|
|
|
|
$(this.$refs.dropdown).dropdown('toggle');
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
|
2018-10-15 14:42:47 +05:30
|
|
|
isDropdownOpen() {
|
2020-05-24 23:13:21 +05:30
|
|
|
return this.$el.classList.contains('show');
|
2018-10-15 14:42:47 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
pipelineActionRequestComplete() {
|
|
|
|
if (this.type === PIPELINES_TABLE) {
|
|
|
|
// warn the table to update
|
|
|
|
eventHub.$emit('refreshPipelinesTable');
|
|
|
|
} else {
|
|
|
|
// close the dropdown in mr widget
|
|
|
|
$(this.$refs.dropdown).dropdown('toggle');
|
|
|
|
}
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
2018-10-15 14:42:47 +05:30
|
|
|
},
|
|
|
|
};
|
2017-08-17 22:00:37 +05:30
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div class="dropdown">
|
|
|
|
<button
|
2018-11-08 19:23:39 +05:30
|
|
|
id="stageDropdown"
|
|
|
|
ref="dropdown"
|
2019-02-15 15:39:39 +05:30
|
|
|
v-gl-tooltip.hover
|
2017-08-17 22:00:37 +05:30
|
|
|
:class="triggerButtonClass"
|
|
|
|
:title="stage.title"
|
2018-11-08 19:23:39 +05:30
|
|
|
class="mini-pipeline-graph-dropdown-toggle js-builds-dropdown-button"
|
2017-08-17 22:00:37 +05:30
|
|
|
data-toggle="dropdown"
|
2018-11-08 19:23:39 +05:30
|
|
|
data-display="static"
|
2017-08-17 22:00:37 +05:30
|
|
|
type="button"
|
|
|
|
aria-haspopup="true"
|
2018-03-17 18:26:18 +05:30
|
|
|
aria-expanded="false"
|
2018-11-08 19:23:39 +05:30
|
|
|
@click="onClickStage"
|
2018-03-17 18:26:18 +05:30
|
|
|
>
|
2019-02-15 15:39:39 +05:30
|
|
|
<span :aria-label="stage.title" aria-hidden="true" class="no-pointer-events">
|
2018-03-17 18:26:18 +05:30
|
|
|
<icon :name="borderlessIcon" />
|
2017-08-17 22:00:37 +05:30
|
|
|
</span>
|
|
|
|
</button>
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
<div
|
2017-08-17 22:00:37 +05:30
|
|
|
class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
|
2018-03-17 18:26:18 +05:30
|
|
|
aria-labelledby="stageDropdown"
|
|
|
|
>
|
2019-02-15 15:39:39 +05:30
|
|
|
<gl-loading-icon v-if="isLoading" />
|
|
|
|
<ul v-else class="js-builds-dropdown-list scrollable-menu">
|
|
|
|
<li v-for="job in dropdownContent" :key="job.id">
|
2018-12-13 13:39:08 +05:30
|
|
|
<job-item
|
2018-11-08 19:23:39 +05:30
|
|
|
:dropdown-length="dropdownContent.length"
|
|
|
|
:job="job"
|
|
|
|
css-class-job-name="mini-pipeline-graph-dropdown-item"
|
|
|
|
@pipelineActionRequestComplete="pipelineActionRequestComplete"
|
|
|
|
/>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
2017-08-17 22:00:37 +05:30
|
|
|
</div>
|
2018-03-17 18:26:18 +05:30
|
|
|
</template>
|