261 lines
7.6 KiB
Vue
261 lines
7.6 KiB
Vue
<script>
|
|
import { reportToSentry } from '../../utils';
|
|
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
|
|
import LinksLayer from '../graph_shared/links_layer.vue';
|
|
import {
|
|
generateColumnsFromLayersListMemoized,
|
|
keepLatestDownstreamPipelines,
|
|
} from '../parsing_utils';
|
|
import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH, STAGE_VIEW } from './constants';
|
|
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
|
|
import StageColumnComponent from './stage_column_component.vue';
|
|
import { validateConfigPaths } from './utils';
|
|
|
|
export default {
|
|
name: 'PipelineGraph',
|
|
components: {
|
|
LinksLayer,
|
|
LinkedGraphWrapper,
|
|
LinkedPipelinesColumn,
|
|
StageColumnComponent,
|
|
},
|
|
props: {
|
|
configPaths: {
|
|
type: Object,
|
|
required: true,
|
|
validator: validateConfigPaths,
|
|
},
|
|
pipeline: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
showLinks: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
viewType: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
isLinkedPipeline: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
computedPipelineInfo: {
|
|
type: Object,
|
|
required: false,
|
|
default: () => ({}),
|
|
},
|
|
skipRetryModal: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: false,
|
|
},
|
|
type: {
|
|
type: String,
|
|
required: false,
|
|
default: MAIN,
|
|
},
|
|
},
|
|
pipelineTypeConstants: {
|
|
DOWNSTREAM,
|
|
UPSTREAM,
|
|
},
|
|
CONTAINER_REF: 'PIPELINE_LINKS_CONTAINER_REF',
|
|
BASE_CONTAINER_ID: 'pipeline-links-container',
|
|
data() {
|
|
return {
|
|
hoveredJobName: '',
|
|
hoveredSourceJobName: '',
|
|
highlightedJobs: [],
|
|
measurements: {
|
|
width: 0,
|
|
height: 0,
|
|
},
|
|
pipelineExpanded: {
|
|
jobName: '',
|
|
expanded: false,
|
|
},
|
|
};
|
|
},
|
|
computed: {
|
|
containerId() {
|
|
return `${this.$options.BASE_CONTAINER_ID}-${this.pipeline.id}`;
|
|
},
|
|
downstreamPipelines() {
|
|
return this.hasDownstreamPipelines
|
|
? keepLatestDownstreamPipelines(this.pipeline.downstream)
|
|
: [];
|
|
},
|
|
layout() {
|
|
return this.isStageView
|
|
? this.pipeline.stages
|
|
: generateColumnsFromLayersListMemoized(
|
|
this.pipeline,
|
|
this.computedPipelineInfo.pipelineLayers,
|
|
);
|
|
},
|
|
hasDownstreamPipelines() {
|
|
return Boolean(this.pipeline?.downstream?.length > 0);
|
|
},
|
|
hasUpstreamPipelines() {
|
|
return Boolean(this.pipeline?.upstream?.length > 0);
|
|
},
|
|
isStageView() {
|
|
return this.viewType === STAGE_VIEW;
|
|
},
|
|
linksData() {
|
|
return this.computedPipelineInfo?.linksData ?? null;
|
|
},
|
|
metricsConfig() {
|
|
return {
|
|
path: this.configPaths.metricsPath,
|
|
collectMetrics: true,
|
|
};
|
|
},
|
|
showJobLinks() {
|
|
return !this.isStageView && this.showLinks;
|
|
},
|
|
// The show downstream check prevents showing redundant linked columns
|
|
showDownstreamPipelines() {
|
|
return (
|
|
this.hasDownstreamPipelines && this.type !== this.$options.pipelineTypeConstants.UPSTREAM
|
|
);
|
|
},
|
|
// The show upstream check prevents showing redundant linked columns
|
|
showUpstreamPipelines() {
|
|
return (
|
|
this.hasUpstreamPipelines && this.type !== this.$options.pipelineTypeConstants.DOWNSTREAM
|
|
);
|
|
},
|
|
upstreamPipelines() {
|
|
return this.hasUpstreamPipelines ? this.pipeline.upstream : [];
|
|
},
|
|
},
|
|
errorCaptured(err, _vm, info) {
|
|
reportToSentry(this.$options.name, `error: ${err}, info: ${info}`);
|
|
},
|
|
mounted() {
|
|
this.getMeasurements();
|
|
},
|
|
methods: {
|
|
getMeasurements() {
|
|
this.measurements = {
|
|
width: this.$refs[this.containerId].scrollWidth,
|
|
height: this.$refs[this.containerId].scrollHeight,
|
|
};
|
|
},
|
|
onError(payload) {
|
|
this.$emit('error', payload);
|
|
},
|
|
setJob(jobName) {
|
|
this.hoveredJobName = jobName;
|
|
},
|
|
setSourceJob(jobName) {
|
|
this.hoveredSourceJobName = jobName;
|
|
},
|
|
slidePipelineContainer() {
|
|
this.$refs.mainPipelineContainer.scrollBy({
|
|
left: ONE_COL_WIDTH,
|
|
top: 0,
|
|
behavior: 'smooth',
|
|
});
|
|
},
|
|
togglePipelineExpanded(jobName, expanded) {
|
|
this.pipelineExpanded = {
|
|
expanded,
|
|
jobName: expanded ? jobName : '',
|
|
};
|
|
},
|
|
updateHighlightedJobs(jobs) {
|
|
this.highlightedJobs = jobs;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
<template>
|
|
<div class="js-pipeline-graph">
|
|
<div
|
|
ref="mainPipelineContainer"
|
|
class="gl-display-flex gl-position-relative gl-bg-gray-10 gl-white-space-nowrap"
|
|
:class="{
|
|
'gl-pipeline-min-h gl-py-5 gl-overflow-auto': !isLinkedPipeline,
|
|
}"
|
|
>
|
|
<linked-graph-wrapper>
|
|
<template #upstream>
|
|
<linked-pipelines-column
|
|
v-if="showUpstreamPipelines"
|
|
:config-paths="configPaths"
|
|
:linked-pipelines="upstreamPipelines"
|
|
:column-title="__('Upstream')"
|
|
:show-links="showJobLinks"
|
|
:skip-retry-modal="skipRetryModal"
|
|
:type="$options.pipelineTypeConstants.UPSTREAM"
|
|
:view-type="viewType"
|
|
@error="onError"
|
|
@setSkipRetryModal="$emit('setSkipRetryModal')"
|
|
/>
|
|
</template>
|
|
<template #main>
|
|
<div :id="containerId" :ref="containerId">
|
|
<links-layer
|
|
:pipeline-data="layout"
|
|
:pipeline-id="pipeline.id"
|
|
:container-id="containerId"
|
|
:container-measurements="measurements"
|
|
:highlighted-job="hoveredJobName"
|
|
:links-data="linksData"
|
|
:metrics-config="metricsConfig"
|
|
:show-links="showJobLinks"
|
|
:view-type="viewType"
|
|
@error="onError"
|
|
@highlightedJobsChange="updateHighlightedJobs"
|
|
>
|
|
<stage-column-component
|
|
v-for="column in layout"
|
|
:key="column.id || column.name"
|
|
:name="column.name"
|
|
:groups="column.groups"
|
|
:action="column.status.action"
|
|
:highlighted-jobs="highlightedJobs"
|
|
:is-stage-view="isStageView"
|
|
:job-hovered="hoveredJobName"
|
|
:skip-retry-modal="skipRetryModal"
|
|
:source-job-hovered="hoveredSourceJobName"
|
|
:pipeline-expanded="pipelineExpanded"
|
|
:pipeline-id="pipeline.id"
|
|
:user-permissions="pipeline.userPermissions"
|
|
@refreshPipelineGraph="$emit('refreshPipelineGraph')"
|
|
@setSkipRetryModal="$emit('setSkipRetryModal')"
|
|
@jobHover="setJob"
|
|
@updateMeasurements="getMeasurements"
|
|
/>
|
|
</links-layer>
|
|
</div>
|
|
</template>
|
|
<template #downstream>
|
|
<linked-pipelines-column
|
|
v-if="showDownstreamPipelines"
|
|
class="gl-mr-6"
|
|
:config-paths="configPaths"
|
|
:linked-pipelines="downstreamPipelines"
|
|
:column-title="__('Downstream')"
|
|
:skip-retry-modal="skipRetryModal"
|
|
:show-links="showJobLinks"
|
|
:type="$options.pipelineTypeConstants.DOWNSTREAM"
|
|
:view-type="viewType"
|
|
data-testid="downstream-pipelines"
|
|
@downstreamHovered="setSourceJob"
|
|
@pipelineExpandToggle="togglePipelineExpanded"
|
|
@refreshPipelineGraph="$emit('refreshPipelineGraph')"
|
|
@setSkipRetryModal="$emit('setSkipRetryModal')"
|
|
@scrollContainer="slidePipelineContainer"
|
|
@error="onError"
|
|
/>
|
|
</template>
|
|
</linked-graph-wrapper>
|
|
</div>
|
|
</div>
|
|
</template>
|