diff options
Diffstat (limited to 'app/assets/javascripts/pipelines/components/graph/graph_component.vue')
-rw-r--r-- | app/assets/javascripts/pipelines/components/graph/graph_component.vue | 270 |
1 files changed, 63 insertions, 207 deletions
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index 16ce279a591..67b2ed3b596 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -1,35 +1,23 @@ <script> -import { escape, capitalize } from 'lodash'; -import { GlLoadingIcon } from '@gitlab/ui'; -import StageColumnComponent from './stage_column_component.vue'; -import GraphWidthMixin from '../../mixins/graph_width_mixin'; +import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue'; import LinkedPipelinesColumn from './linked_pipelines_column.vue'; -import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin'; -import { UPSTREAM, DOWNSTREAM, MAIN } from './constants'; +import StageColumnComponent from './stage_column_component.vue'; +import { DOWNSTREAM, MAIN, UPSTREAM } from './constants'; export default { name: 'PipelineGraph', components: { - StageColumnComponent, - GlLoadingIcon, + LinkedGraphWrapper, LinkedPipelinesColumn, + StageColumnComponent, }, - mixins: [GraphWidthMixin, GraphBundleMixin], props: { - isLoading: { - type: Boolean, - required: true, - }, - pipeline: { - type: Object, - required: true, - }, isLinkedPipeline: { type: Boolean, required: false, default: false, }, - mediator: { + pipeline: { type: Object, required: true, }, @@ -39,12 +27,13 @@ export default { default: MAIN, }, }, - upstream: UPSTREAM, - downstream: DOWNSTREAM, + pipelineTypeConstants: { + DOWNSTREAM, + UPSTREAM, + }, data() { return { - downstreamMarginTop: null, - jobName: null, + hoveredJobName: '', pipelineExpanded: { jobName: '', expanded: false, @@ -52,219 +41,86 @@ export default { }; }, computed: { + downstreamPipelines() { + return this.hasDownstreamPipelines ? this.pipeline.downstream : []; + }, graph() { - return this.pipeline.details?.stages; + return this.pipeline.stages; }, - hasUpstream() { - return ( - this.type !== this.$options.downstream && - this.upstreamPipelines && - this.pipeline.triggered_by !== null - ); + hasDownstreamPipelines() { + return Boolean(this.pipeline?.downstream?.length > 0); }, - upstreamPipelines() { - return this.pipeline.triggered_by; + hasUpstreamPipelines() { + return Boolean(this.pipeline?.upstream?.length > 0); }, - hasDownstream() { + // The two show checks prevent upstream / downstream from showing redundant linked columns + showDownstreamPipelines() { return ( - this.type !== this.$options.upstream && - this.downstreamPipelines && - this.pipeline.triggered.length > 0 + this.hasDownstreamPipelines && this.type !== this.$options.pipelineTypeConstants.UPSTREAM ); }, - downstreamPipelines() { - return this.pipeline.triggered; - }, - expandedUpstream() { + showUpstreamPipelines() { return ( - this.pipeline.triggered_by && - Array.isArray(this.pipeline.triggered_by) && - this.pipeline.triggered_by.find(el => el.isExpanded) + this.hasUpstreamPipelines && this.type !== this.$options.pipelineTypeConstants.DOWNSTREAM ); }, - expandedDownstream() { - return this.pipeline.triggered && this.pipeline.triggered.find(el => el.isExpanded); - }, - pipelineTypeUpstream() { - return this.type !== this.$options.downstream && this.expandedUpstream; - }, - pipelineTypeDownstream() { - return this.type !== this.$options.upstream && this.expandedDownstream; - }, - pipelineProjectId() { - return this.pipeline.project.id; + upstreamPipelines() { + return this.hasUpstreamPipelines ? this.pipeline.upstream : []; }, }, methods: { - 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); - }, - 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 - * offsetTop and then subtracting 15 - */ - this.downstreamMarginTop = this.calculateMarginTop(downstreamNode, 15); - - /** - * 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 - */ - if (this.expandedDownstream?.id !== pipeline.id) { - this.$emit('onResetDownstream', this.pipeline, pipeline); - } - - this.$emit('onClickDownstreamPipeline', pipeline); - }, - calculateMarginTop(downstreamNode, pixelDiff) { - return `${downstreamNode.offsetTop - downstreamNode.offsetParent.offsetTop - pixelDiff}px`; - }, - hasOnlyOneJob(stage) { - return stage.groups.length === 1; - }, - hasUpstreamColumn(index) { - return index === 0 && this.hasUpstream; - }, setJob(jobName) { - this.jobName = jobName; + this.hoveredJobName = jobName; }, - setPipelineExpanded(jobName, expanded) { - if (expanded) { - this.pipelineExpanded = { - jobName, - expanded, - }; - } else { - this.pipelineExpanded = { - expanded, - jobName: '', - }; - } + togglePipelineExpanded(jobName, expanded) { + this.pipelineExpanded = { + expanded, + jobName: expanded ? jobName : '', + }; }, }, }; </script> <template> - <div class="build-content middle-block js-pipeline-graph"> + <div class="js-pipeline-graph"> <div - class="pipeline-visualization pipeline-graph" - :class="{ 'pipeline-tab-content': !isLinkedPipeline }" + class="gl-pipeline-min-h gl-display-flex gl-position-relative gl-overflow-auto gl-bg-gray-10 gl-white-space-nowrap" + :class="{ 'gl-py-5': !isLinkedPipeline }" > - <div - :style="{ - paddingLeft: `${graphLeftPadding}px`, - paddingRight: `${graphRightPadding}px`, - }" - > - <gl-loading-icon v-if="isLoading" class="m-auto" size="lg" /> - - <pipeline-graph - v-if="pipelineTypeUpstream" - :type="$options.upstream" - class="d-inline-block upstream-pipeline" - :class="`js-upstream-pipeline-${expandedUpstream.id}`" - :is-loading="false" - :pipeline="expandedUpstream" - :is-linked-pipeline="true" - :mediator="mediator" - @onClickUpstreamPipeline="clickUpstreamPipeline" - @refreshPipelineGraph="requestRefreshPipelineGraph" - /> - - <linked-pipelines-column - v-if="hasUpstream" - :type="$options.upstream" - :linked-pipelines="upstreamPipelines" - :column-title="__('Upstream')" - :project-id="pipelineProjectId" - @linkedPipelineClick="$emit('onClickUpstreamPipeline', $event)" - /> - - <ul - v-if="!isLoading" - :class="{ - 'inline js-has-linked-pipelines': hasDownstream || hasUpstream, - }" - class="stage-column-list align-top" - > + <linked-graph-wrapper> + <template #upstream> + <linked-pipelines-column + v-if="showUpstreamPipelines" + :linked-pipelines="upstreamPipelines" + :column-title="__('Upstream')" + :type="$options.pipelineTypeConstants.UPSTREAM" + @error="emit('error', errorType)" + /> + </template> + <template #main> <stage-column-component - v-for="(stage, index) in graph" + v-for="stage in graph" :key="stage.name" - :class="{ - 'has-upstream gl-ml-11': hasUpstreamColumn(index), - 'has-only-one-job': hasOnlyOneJob(stage), - 'gl-mr-26': shouldAddRightMargin(index), - }" - :title="capitalizeStageName(stage.name)" + :title="stage.name" :groups="stage.groups" - :stage-connector-class="stageConnectorClass(index, stage)" - :is-first-column="isFirstColumn(index)" - :has-upstream="hasUpstream" :action="stage.status.action" - :job-hovered="jobName" + :job-hovered="hoveredJobName" :pipeline-expanded="pipelineExpanded" - @refreshPipelineGraph="refreshPipelineGraph" + @refreshPipelineGraph="$emit('refreshPipelineGraph')" /> - </ul> - - <linked-pipelines-column - v-if="hasDownstream" - :type="$options.downstream" - :linked-pipelines="downstreamPipelines" - :column-title="__('Downstream')" - :project-id="pipelineProjectId" - @linkedPipelineClick="handleClickedDownstream" - @downstreamHovered="setJob" - @pipelineExpandToggle="setPipelineExpanded" - /> - - <pipeline-graph - v-if="pipelineTypeDownstream" - :type="$options.downstream" - class="d-inline-block" - :class="`js-downstream-pipeline-${expandedDownstream.id}`" - :is-loading="false" - :pipeline="expandedDownstream" - :is-linked-pipeline="true" - :style="{ 'margin-top': downstreamMarginTop }" - :mediator="mediator" - @onClickDownstreamPipeline="clickDownstreamPipeline" - @refreshPipelineGraph="requestRefreshPipelineGraph" - /> - </div> + </template> + <template #downstream> + <linked-pipelines-column + v-if="showDownstreamPipelines" + :linked-pipelines="downstreamPipelines" + :column-title="__('Downstream')" + :type="$options.pipelineTypeConstants.DOWNSTREAM" + @downstreamHovered="setJob" + @pipelineExpandToggle="togglePipelineExpanded" + @error="emit('error', errorType)" + /> + </template> + </linked-graph-wrapper> </div> </div> </template> |