summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-04-20 23:50:22 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-20 23:50:22 +0000
commit9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch)
tree70467ae3692a0e35e5ea56bcb803eb512a10bedb /app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
parent4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff)
downloadgitlab-ce-9dc93a4519d9d5d7be48ff274127136236a3adb3.tar.gz
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue')
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue218
1 files changed, 70 insertions, 148 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
index 707d6966e77..3ba0d7d0120 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -1,11 +1,8 @@
<script>
import { GlAlert } from '@gitlab/ui';
import { __ } from '~/locale';
-import { CI_CONFIG_STATUS_INVALID } from '~/pipeline_editor/constants';
-import { DRAW_FAILURE, DEFAULT, INVALID_CI_CONFIG, EMPTY_PIPELINE_DATA } from '../../constants';
-import { createJobsHash, generateJobNeedsDict } from '../../utils';
-import { generateLinksData } from '../graph_shared/drawing_utils';
-import { parseData } from '../parsing_utils';
+import { DRAW_FAILURE, DEFAULT } from '../../constants';
+import LinksLayer from '../graph_shared/links_layer.vue';
import JobPill from './job_pill.vue';
import StagePill from './stage_pill.vue';
@@ -13,18 +10,16 @@ export default {
components: {
GlAlert,
JobPill,
+ LinksLayer,
StagePill,
},
CONTAINER_REF: 'PIPELINE_GRAPH_CONTAINER_REF',
- CONTAINER_ID: 'pipeline-graph-container',
+ BASE_CONTAINER_ID: 'pipeline-graph-container',
+ PIPELINE_ID: 0,
STROKE_WIDTH: 2,
errorTexts: {
[DRAW_FAILURE]: __('Could not draw the lines for job relationships'),
[DEFAULT]: __('An unknown error occurred.'),
- [EMPTY_PIPELINE_DATA]: __(
- 'The visualization will appear in this tab when the CI/CD configuration file is populated with valid syntax.',
- ),
- [INVALID_CI_CONFIG]: __('Your CI configuration file is invalid.'),
},
props: {
pipelineData: {
@@ -36,33 +31,16 @@ export default {
return {
failureType: null,
highlightedJob: null,
- links: [],
- needsObject: null,
- height: 0,
- width: 0,
+ highlightedJobs: [],
+ measurements: {
+ height: 0,
+ width: 0,
+ },
};
},
computed: {
- hideGraph() {
- // We won't even try to render the graph with these condition
- // because it would cause additional errors down the line for the user
- // which is confusing.
- return this.isPipelineDataEmpty || this.isInvalidCiConfig;
- },
- pipelineStages() {
- return this.pipelineData?.stages || [];
- },
- isPipelineDataEmpty() {
- return !this.isInvalidCiConfig && this.pipelineStages.length === 0;
- },
- isInvalidCiConfig() {
- return this.pipelineData?.status === CI_CONFIG_STATUS_INVALID;
- },
- hasError() {
- return this.failureType;
- },
- hasHighlightedJob() {
- return Boolean(this.highlightedJob);
+ containerId() {
+ return `${this.$options.BASE_CONTAINER_ID}-${this.$options.PIPELINE_ID}`;
},
failure() {
switch (this.failureType) {
@@ -72,18 +50,6 @@ export default {
variant: 'danger',
dismissible: true,
};
- case EMPTY_PIPELINE_DATA:
- return {
- text: this.$options.errorTexts[EMPTY_PIPELINE_DATA],
- variant: 'tip',
- dismissible: false,
- };
- case INVALID_CI_CONFIG:
- return {
- text: this.$options.errorTexts[INVALID_CI_CONFIG],
- variant: 'danger',
- dismissible: false,
- };
default:
return {
text: this.$options.errorTexts[DEFAULT],
@@ -92,56 +58,32 @@ export default {
};
}
},
- viewBox() {
- return [0, 0, this.width, this.height];
+ hasError() {
+ return this.failureType;
},
- highlightedJobs() {
- // If you are hovering on a job, then the jobs we want to highlight are:
- // The job you are currently hovering + all of its needs.
- return [this.highlightedJob, ...this.needsObject[this.highlightedJob]];
+ hasHighlightedJob() {
+ return Boolean(this.highlightedJob);
},
- highlightedLinks() {
- // If you are hovering on a job, then the links we want to highlight are:
- // All the links whose `source` and `target` are highlighted jobs.
- if (this.hasHighlightedJob) {
- const filteredLinks = this.links.filter((link) => {
- return (
- this.highlightedJobs.includes(link.source) && this.highlightedJobs.includes(link.target)
- );
- });
-
- return filteredLinks.map((link) => link.ref);
- }
-
- return [];
+ pipelineStages() {
+ return this.pipelineData?.stages || [];
},
},
watch: {
pipelineData: {
immediate: true,
handler() {
- if (this.isPipelineDataEmpty) {
- this.reportFailure(EMPTY_PIPELINE_DATA);
- } else if (this.isInvalidCiConfig) {
- this.reportFailure(INVALID_CI_CONFIG);
- } else {
- this.$nextTick(() => {
- this.computeGraphDimensions();
- this.prepareLinkData();
- });
- }
+ this.$nextTick(() => {
+ this.computeGraphDimensions();
+ });
},
},
},
methods: {
- prepareLinkData() {
- try {
- const arrayOfJobs = this.pipelineStages.flatMap(({ groups }) => groups);
- const parsedData = parseData(arrayOfJobs);
- this.links = generateLinksData(parsedData, this.$options.CONTAINER_ID);
- } catch {
- this.reportFailure(DRAW_FAILURE);
- }
+ computeGraphDimensions() {
+ this.measurements = {
+ width: this.$refs[this.$options.CONTAINER_REF].scrollWidth,
+ height: this.$refs[this.$options.CONTAINER_REF].scrollHeight,
+ };
},
getStageBackgroundClasses(index) {
const { length } = this.pipelineStages;
@@ -161,22 +103,14 @@ export default {
return '';
},
- highlightNeeds(uniqueJobId) {
- // The first time we hover, we create the object where
- // we store all the data to properly highlight the needs.
- if (!this.needsObject) {
- const jobs = createJobsHash(this.pipelineStages);
- this.needsObject = generateJobNeedsDict(jobs) ?? {};
- }
-
- this.highlightedJob = uniqueJobId;
+ isJobHighlighted(jobName) {
+ return this.highlightedJobs.includes(jobName);
},
- removeHighlightNeeds() {
- this.highlightedJob = null;
+ onError(error) {
+ this.reportFailure(error.type);
},
- computeGraphDimensions() {
- this.width = `${this.$refs[this.$options.CONTAINER_REF].scrollWidth}`;
- this.height = `${this.$refs[this.$options.CONTAINER_REF].scrollHeight}`;
+ removeHoveredJob() {
+ this.highlightedJob = null;
},
reportFailure(errorType) {
this.failureType = errorType;
@@ -184,17 +118,11 @@ export default {
resetFailure() {
this.failureType = null;
},
- isJobHighlighted(jobName) {
- return this.highlightedJobs.includes(jobName);
+ setHoveredJob(jobName) {
+ this.highlightedJob = jobName;
},
- isLinkHighlighted(linkRef) {
- return this.highlightedLinks.includes(linkRef);
- },
- getLinkClasses(link) {
- return [
- this.isLinkHighlighted(link.ref) ? 'gl-stroke-blue-400' : 'gl-stroke-gray-200',
- { 'gl-opacity-3': this.hasHighlightedJob && !this.isLinkHighlighted(link.ref) },
- ];
+ updateHighlightedJobs(jobs) {
+ this.highlightedJobs = jobs;
},
},
};
@@ -209,50 +137,44 @@ export default {
>
{{ failure.text }}
</gl-alert>
- <div
- v-if="!hideGraph"
- :id="$options.CONTAINER_ID"
- :ref="$options.CONTAINER_REF"
- class="gl-display-flex gl-bg-gray-50 gl-px-4 gl-overflow-auto gl-relative gl-py-7"
- data-testid="graph-container"
- >
- <svg :viewBox="viewBox" :width="width" :height="height" class="gl-absolute">
- <path
- v-for="link in links"
- :key="link.path"
- :ref="link.ref"
- :d="link.path"
- class="gl-fill-transparent gl-transition-duration-slow gl-transition-timing-function-ease"
- :class="getLinkClasses(link)"
- :stroke-width="$options.STROKE_WIDTH"
- />
- </svg>
- <div
- v-for="(stage, index) in pipelineStages"
- :key="`${stage.name}-${index}`"
- class="gl-flex-direction-column"
+ <div :id="containerId" :ref="$options.CONTAINER_REF" data-testid="graph-container">
+ <links-layer
+ :pipeline-data="pipelineStages"
+ :pipeline-id="$options.PIPELINE_ID"
+ :container-id="containerId"
+ :container-measurements="measurements"
+ :highlighted-job="highlightedJob"
+ @highlightedJobsChange="updateHighlightedJobs"
+ @error="onError"
>
<div
- class="gl-display-flex gl-align-items-center gl-bg-white gl-w-full gl-px-8 gl-py-4 gl-mb-5"
- :class="getStageBackgroundClasses(index)"
- data-testid="stage-background"
- >
- <stage-pill :stage-name="stage.name" :is-empty="stage.groups.length === 0" />
- </div>
- <div
- class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8"
+ v-for="(stage, index) in pipelineStages"
+ :key="`${stage.name}-${index}`"
+ class="gl-flex-direction-column"
>
- <job-pill
- v-for="group in stage.groups"
- :key="group.name"
- :job-name="group.name"
- :is-highlighted="hasHighlightedJob && isJobHighlighted(group.name)"
- :is-faded-out="hasHighlightedJob && !isJobHighlighted(group.name)"
- @on-mouse-enter="highlightNeeds"
- @on-mouse-leave="removeHighlightNeeds"
- />
+ <div
+ class="gl-display-flex gl-align-items-center gl-bg-white gl-w-full gl-px-8 gl-py-4 gl-mb-5"
+ :class="getStageBackgroundClasses(index)"
+ data-testid="stage-background"
+ >
+ <stage-pill :stage-name="stage.name" :is-empty="stage.groups.length === 0" />
+ </div>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8"
+ >
+ <job-pill
+ v-for="group in stage.groups"
+ :key="group.name"
+ :job-name="group.name"
+ :pipeline-id="$options.PIPELINE_ID"
+ :is-highlighted="hasHighlightedJob && isJobHighlighted(group.name)"
+ :is-faded-out="hasHighlightedJob && !isJobHighlighted(group.name)"
+ @on-mouse-enter="setHoveredJob"
+ @on-mouse-leave="removeHoveredJob"
+ />
+ </div>
</div>
- </div>
+ </links-layer>
</div>
</div>
</template>