debian-mirror-gitlab/app/assets/javascripts/pipelines/components/graph/graph_component.vue

271 lines
7.9 KiB
Vue
Raw Normal View History

2017-08-17 22:00:37 +05:30
<script>
2021-01-03 14:25:43 +05:30
import { escape, capitalize } from 'lodash';
2019-02-15 15:39:39 +05:30
import { GlLoadingIcon } from '@gitlab/ui';
2018-05-09 12:01:36 +05:30
import StageColumnComponent from './stage_column_component.vue';
2019-12-21 20:55:43 +05:30
import GraphWidthMixin from '../../mixins/graph_width_mixin';
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
2021-01-29 00:20:46 +05:30
import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
2017-08-17 22:00:37 +05:30
2018-05-09 12:01:36 +05:30
export default {
2019-12-21 20:55:43 +05:30
name: 'PipelineGraph',
2018-05-09 12:01:36 +05:30
components: {
StageColumnComponent,
2018-12-13 13:39:08 +05:30
GlLoadingIcon,
2019-12-21 20:55:43 +05:30
LinkedPipelinesColumn,
},
2021-01-03 14:25:43 +05:30
mixins: [GraphWidthMixin, GraphBundleMixin],
2019-12-21 20:55:43 +05:30
props: {
isLoading: {
type: Boolean,
required: true,
},
pipeline: {
type: Object,
required: true,
},
isLinkedPipeline: {
type: Boolean,
required: false,
default: false,
},
mediator: {
type: Object,
required: true,
},
type: {
type: String,
required: false,
2021-01-29 00:20:46 +05:30
default: MAIN,
2019-12-21 20:55:43 +05:30
},
},
2021-01-29 00:20:46 +05:30
upstream: UPSTREAM,
downstream: DOWNSTREAM,
2019-12-21 20:55:43 +05:30
data() {
return {
2020-03-13 15:44:24 +05:30
downstreamMarginTop: null,
2020-07-28 23:09:34 +05:30
jobName: null,
2020-11-24 15:15:51 +05:30
pipelineExpanded: {
jobName: '',
expanded: false,
},
2019-12-21 20:55:43 +05:30
};
},
computed: {
2021-01-03 14:25:43 +05:30
graph() {
return this.pipeline.details?.stages;
},
2021-01-29 00:20:46 +05:30
hasUpstream() {
2019-12-21 20:55:43 +05:30
return (
this.type !== this.$options.downstream &&
2021-01-29 00:20:46 +05:30
this.upstreamPipelines &&
2019-12-21 20:55:43 +05:30
this.pipeline.triggered_by !== null
);
},
2021-01-29 00:20:46 +05:30
upstreamPipelines() {
2019-12-21 20:55:43 +05:30
return this.pipeline.triggered_by;
},
2021-01-29 00:20:46 +05:30
hasDownstream() {
2019-12-21 20:55:43 +05:30
return (
this.type !== this.$options.upstream &&
2021-01-29 00:20:46 +05:30
this.downstreamPipelines &&
2019-12-21 20:55:43 +05:30
this.pipeline.triggered.length > 0
);
},
2021-01-29 00:20:46 +05:30
downstreamPipelines() {
2019-12-21 20:55:43 +05:30
return this.pipeline.triggered;
},
2021-01-29 00:20:46 +05:30
expandedUpstream() {
2019-12-21 20:55:43 +05:30
return (
this.pipeline.triggered_by &&
2020-03-13 15:44:24 +05:30
Array.isArray(this.pipeline.triggered_by) &&
2019-12-21 20:55:43 +05:30
this.pipeline.triggered_by.find(el => el.isExpanded)
);
},
2021-01-29 00:20:46 +05:30
expandedDownstream() {
2019-12-21 20:55:43 +05:30
return this.pipeline.triggered && this.pipeline.triggered.find(el => el.isExpanded);
},
pipelineTypeUpstream() {
2021-01-29 00:20:46 +05:30
return this.type !== this.$options.downstream && this.expandedUpstream;
2019-12-21 20:55:43 +05:30
},
pipelineTypeDownstream() {
2021-01-29 00:20:46 +05:30
return this.type !== this.$options.upstream && this.expandedDownstream;
2019-12-21 20:55:43 +05:30
},
2020-03-13 15:44:24 +05:30
pipelineProjectId() {
return this.pipeline.project.id;
},
2019-12-21 20:55:43 +05:30
},
methods: {
2021-01-03 14:25:43 +05:30
capitalizeStageName(name) {
const escapedName = escape(name);
return capitalize(escapedName);
},
isFirstColumn(index) {
return index === 0;
},
stageConnectorClass(index, stage) {
let className;
// If it's the first stage column and only has one job
if (this.isFirstColumn(index) && stage.groups.length === 1) {
className = 'no-margin';
} else if (index > 0) {
// If it is not the first column
className = 'left-margin';
}
return className;
},
refreshPipelineGraph() {
this.$emit('refreshPipelineGraph');
},
/**
* CSS class is applied:
* - if pipeline graph contains only one stage column component
*
* @param {number} index
* @returns {boolean}
*/
shouldAddRightMargin(index) {
return !(index === this.graph.length - 1);
},
2020-03-13 15:44:24 +05:30
handleClickedDownstream(pipeline, clickedIndex, downstreamNode) {
/**
* Calculates the margin top of the clicked downstream pipeline by
* subtracting the clicked downstream pipelines offsetTop by it's parent's
2020-07-28 23:09:34 +05:30
* offsetTop and then subtracting 15
2020-03-13 15:44:24 +05:30
*/
2020-07-28 23:09:34 +05:30
this.downstreamMarginTop = this.calculateMarginTop(downstreamNode, 15);
2020-03-13 15:44:24 +05:30
2020-04-22 19:07:51 +05:30
/**
* If the expanded trigger is defined and the id is different than the
* pipeline we clicked, then it means we clicked on a sibling downstream link
* and we want to reset the pipeline store. Triggering the reset without
* this condition would mean not allowing downstreams of downstreams to expand
*/
2021-01-29 00:20:46 +05:30
if (this.expandedDownstream?.id !== pipeline.id) {
this.$emit('onResetDownstream', this.pipeline, pipeline);
2020-04-22 19:07:51 +05:30
}
2021-01-29 00:20:46 +05:30
this.$emit('onClickDownstreamPipeline', pipeline);
2019-12-21 20:55:43 +05:30
},
2020-03-13 15:44:24 +05:30
calculateMarginTop(downstreamNode, pixelDiff) {
return `${downstreamNode.offsetTop - downstreamNode.offsetParent.offsetTop - pixelDiff}px`;
},
2019-12-21 20:55:43 +05:30
hasOnlyOneJob(stage) {
return stage.groups.length === 1;
},
2021-01-29 00:20:46 +05:30
hasUpstreamColumn(index) {
return index === 0 && this.hasUpstream;
2019-12-21 20:55:43 +05:30
},
2020-07-28 23:09:34 +05:30
setJob(jobName) {
this.jobName = jobName;
},
2020-11-24 15:15:51 +05:30
setPipelineExpanded(jobName, expanded) {
if (expanded) {
this.pipelineExpanded = {
jobName,
expanded,
};
} else {
this.pipelineExpanded = {
expanded,
jobName: '',
};
}
},
2018-05-09 12:01:36 +05:30
},
};
2017-08-17 22:00:37 +05:30
</script>
<template>
<div class="build-content middle-block js-pipeline-graph">
2019-12-21 20:55:43 +05:30
<div
class="pipeline-visualization pipeline-graph"
:class="{ 'pipeline-tab-content': !isLinkedPipeline }"
>
2019-12-04 20:38:33 +05:30
<div
:style="{
paddingLeft: `${graphLeftPadding}px`,
paddingRight: `${graphRightPadding}px`,
}"
>
2020-04-22 19:07:51 +05:30
<gl-loading-icon v-if="isLoading" class="m-auto" size="lg" />
2017-08-17 22:00:37 +05:30
2019-12-21 20:55:43 +05:30
<pipeline-graph
v-if="pipelineTypeUpstream"
2021-01-29 00:20:46 +05:30
:type="$options.upstream"
2019-12-21 20:55:43 +05:30
class="d-inline-block upstream-pipeline"
2021-01-29 00:20:46 +05:30
:class="`js-upstream-pipeline-${expandedUpstream.id}`"
2019-12-21 20:55:43 +05:30
:is-loading="false"
2021-01-29 00:20:46 +05:30
:pipeline="expandedUpstream"
2019-12-21 20:55:43 +05:30
:is-linked-pipeline="true"
:mediator="mediator"
2021-01-29 00:20:46 +05:30
@onClickUpstreamPipeline="clickUpstreamPipeline"
2019-12-21 20:55:43 +05:30
@refreshPipelineGraph="requestRefreshPipelineGraph"
/>
<linked-pipelines-column
2021-01-29 00:20:46 +05:30
v-if="hasUpstream"
:type="$options.upstream"
:linked-pipelines="upstreamPipelines"
2019-12-21 20:55:43 +05:30
:column-title="__('Upstream')"
2020-03-13 15:44:24 +05:30
:project-id="pipelineProjectId"
2021-01-29 00:20:46 +05:30
@linkedPipelineClick="$emit('onClickUpstreamPipeline', $event)"
2019-12-21 20:55:43 +05:30
/>
<ul
v-if="!isLoading"
:class="{
2021-01-29 00:20:46 +05:30
'inline js-has-linked-pipelines': hasDownstream || hasUpstream,
2019-12-21 20:55:43 +05:30
}"
class="stage-column-list align-top"
>
2019-12-04 20:38:33 +05:30
<stage-column-component
v-for="(stage, index) in graph"
:key="stage.name"
:class="{
2021-01-29 00:20:46 +05:30
'has-upstream gl-ml-11': hasUpstreamColumn(index),
2019-12-21 20:55:43 +05:30
'has-only-one-job': hasOnlyOneJob(stage),
2020-07-28 23:09:34 +05:30
'gl-mr-26': shouldAddRightMargin(index),
2019-12-04 20:38:33 +05:30
}"
:title="capitalizeStageName(stage.name)"
:groups="stage.groups"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
2021-01-29 00:20:46 +05:30
:has-upstream="hasUpstream"
2019-12-04 20:38:33 +05:30
:action="stage.status.action"
2020-07-28 23:09:34 +05:30
:job-hovered="jobName"
2020-11-24 15:15:51 +05:30
:pipeline-expanded="pipelineExpanded"
2019-12-04 20:38:33 +05:30
@refreshPipelineGraph="refreshPipelineGraph"
/>
</ul>
2019-12-21 20:55:43 +05:30
<linked-pipelines-column
2021-01-29 00:20:46 +05:30
v-if="hasDownstream"
:type="$options.downstream"
:linked-pipelines="downstreamPipelines"
2019-12-21 20:55:43 +05:30
:column-title="__('Downstream')"
2020-03-13 15:44:24 +05:30
:project-id="pipelineProjectId"
2019-12-21 20:55:43 +05:30
@linkedPipelineClick="handleClickedDownstream"
2020-07-28 23:09:34 +05:30
@downstreamHovered="setJob"
2020-11-24 15:15:51 +05:30
@pipelineExpandToggle="setPipelineExpanded"
2019-12-21 20:55:43 +05:30
/>
<pipeline-graph
v-if="pipelineTypeDownstream"
2021-01-29 00:20:46 +05:30
:type="$options.downstream"
2019-12-21 20:55:43 +05:30
class="d-inline-block"
2021-01-29 00:20:46 +05:30
:class="`js-downstream-pipeline-${expandedDownstream.id}`"
2019-12-21 20:55:43 +05:30
:is-loading="false"
2021-01-29 00:20:46 +05:30
:pipeline="expandedDownstream"
2019-12-21 20:55:43 +05:30
:is-linked-pipeline="true"
2020-03-13 15:44:24 +05:30
:style="{ 'margin-top': downstreamMarginTop }"
2019-12-21 20:55:43 +05:30
:mediator="mediator"
2021-01-29 00:20:46 +05:30
@onClickDownstreamPipeline="clickDownstreamPipeline"
2019-12-21 20:55:43 +05:30
@refreshPipelineGraph="requestRefreshPipelineGraph"
/>
2019-12-04 20:38:33 +05:30
</div>
2017-08-17 22:00:37 +05:30
</div>
</div>
</template>