summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pipelines
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-19 23:18:09 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-19 23:18:09 +0000
commit6ed4ec3e0b1340f96b7c043ef51d1b33bbe85fde (patch)
treedc4d20fe6064752c0bd323187252c77e0a89144b /app/assets/javascripts/pipelines
parent9868dae7fc0655bd7ce4a6887d4e6d487690eeed (diff)
downloadgitlab-ce-6ed4ec3e0b1340f96b7c043ef51d1b33bbe85fde.tar.gz
Add latest changes from gitlab-org/gitlab@15-4-stable-eev15.4.0-rc42
Diffstat (limited to 'app/assets/javascripts/pipelines')
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue39
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue12
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/performance_insights_modal.vue171
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue12
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/accessors/linked_pipelines_accessors.js14
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/job_item.vue (renamed from app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue)2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue132
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue103
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue (renamed from app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue)4
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue (renamed from app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue)7
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue33
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue10
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue42
-rw-r--r--app/assets/javascripts/pipelines/constants.js6
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_performance_insights.query.graphql28
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql1
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_header.js4
-rw-r--r--app/assets/javascripts/pipelines/pipeline_tabs.js9
-rw-r--r--app/assets/javascripts/pipelines/utils.js21
31 files changed, 378 insertions, 329 deletions
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 31a34ab4fb5..1a05710a13e 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -170,7 +170,7 @@ export default {
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 gl-border-t-solid gl-border-t-1 gl-border-gray-100': !isLinkedPipeline,
+ 'gl-pipeline-min-h gl-py-5 gl-overflow-auto': !isLinkedPipeline,
}"
>
<linked-graph-wrapper>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
index 14872c34afb..f822e2c0874 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
@@ -281,7 +281,6 @@ export default {
:type="graphViewType"
:show-links="showLinks"
:tip-previously-dismissed="hoverTipPreviouslyDismissed"
- :is-pipeline-complete="pipeline.complete"
@dismissHoverTip="handleTipDismissal"
@updateViewType="updateViewType"
@updateShowLinksState="updateShowLinksState"
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
index a8c5d85f4ed..6d8c35f4482 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
@@ -1,33 +1,19 @@
<script>
-import {
- GlAlert,
- GlButton,
- GlButtonGroup,
- GlLoadingIcon,
- GlToggle,
- GlModalDirective,
-} from '@gitlab/ui';
+import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon, GlToggle } from '@gitlab/ui';
import { __, s__ } from '~/locale';
-import Tracking from '~/tracking';
-import PerformanceInsightsModal from '../performance_insights_modal.vue';
-import { performanceModalId } from '../../constants';
import { STAGE_VIEW, LAYER_VIEW } from './constants';
export default {
name: 'GraphViewSelector',
- performanceModalId,
+
components: {
GlAlert,
GlButton,
GlButtonGroup,
GlLoadingIcon,
GlToggle,
- PerformanceInsightsModal,
- },
- directives: {
- GlModal: GlModalDirective,
},
- mixins: [Tracking.mixin()],
+
props: {
showLinks: {
type: Boolean,
@@ -41,10 +27,6 @@ export default {
type: String,
required: true,
},
- isPipelineComplete: {
- type: Boolean,
- required: true,
- },
},
data() {
return {
@@ -59,7 +41,6 @@ export default {
hoverTipText: __('Tip: Hover over a job to see the jobs it depends on to run.'),
linksLabelText: s__('GraphViewType|Show dependencies'),
viewLabelText: __('Group jobs by'),
- performanceBtnText: __('Performance insights'),
},
views: {
[STAGE_VIEW]: {
@@ -150,9 +131,6 @@ export default {
this.$emit('updateShowLinksState', val);
});
},
- trackInsightsClick() {
- this.track('click_insights_button', { label: 'performance_insights' });
- },
},
};
</script>
@@ -178,15 +156,6 @@ export default {
</gl-button>
</gl-button-group>
- <gl-button
- v-if="isPipelineComplete"
- v-gl-modal="$options.performanceModalId"
- data-testid="pipeline-insights-btn"
- @click="trackInsightsClick"
- >
- {{ $options.i18n.performanceBtnText }}
- </gl-button>
-
<div v-if="showLinksToggle" class="gl-display-flex gl-align-items-center">
<gl-toggle
v-model="showLinksActive"
@@ -202,7 +171,5 @@ export default {
<gl-alert v-if="showTip" class="gl-my-5" variant="tip" @dismiss="dismissTip">
{{ $options.i18n.hoverTipText }}
</gl-alert>
-
- <performance-insights-modal />
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index 8d764fad0c5..02d0c07ea54 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -82,7 +82,9 @@ export default {
:stage-name="stageName"
/>
- <div class="gl-font-weight-100 gl-font-size-lg gl-ml-n4">{{ group.size }}</div>
+ <div class="gl-font-weight-100 gl-font-size-lg gl-ml-n4 gl-align-self-center">
+ {{ group.size }}
+ </div>
</div>
</button>
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index 6ab4eb58977..4aec28295bd 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -1,5 +1,5 @@
<script>
-import { capitalize, escape, isEmpty } from 'lodash';
+import { escape, isEmpty } from 'lodash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { reportToSentry } from '../../utils';
import MainGraphWrapper from '../graph_shared/main_graph_wrapper.vue';
@@ -64,8 +64,7 @@ export default {
},
},
jobClasses: [
- 'gl-py-3',
- 'gl-px-4',
+ 'gl-p-3',
'gl-border-gray-100',
'gl-border-solid',
'gl-border-1',
@@ -92,9 +91,6 @@ export default {
columnSpacingClass() {
return this.isStageView ? 'gl-px-6' : 'gl-px-9';
},
- formattedTitle() {
- return capitalize(escape(this.name));
- },
hasAction() {
return !isEmpty(this.action);
},
@@ -141,8 +137,8 @@ export default {
class="gl-display-flex gl-justify-content-space-between gl-relative"
:class="$options.titleClasses"
>
- <span :title="formattedTitle" class="gl-text-truncate gl-pr-3 gl-w-85p">
- {{ formattedTitle }}
+ <span :title="name" class="gl-text-truncate gl-pr-3 gl-w-85p">
+ {{ name }}
</span>
<action-component
v-if="hasAction && canUpdatePipeline"
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index fabae62fc45..a36d5d9b58f 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -9,7 +9,7 @@ import {
} from '@gitlab/ui';
import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import ciHeader from '~/vue_shared/components/header_ci_component.vue';
+import CiHeader from '~/vue_shared/components/header_ci_component.vue';
import {
LOAD_FAILURE,
POST_FAILURE,
@@ -33,7 +33,7 @@ export default {
pipelineRetry: 'pipelineRetry',
finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
components: {
- ciHeader,
+ CiHeader,
GlAlert,
GlButton,
GlLoadingIcon,
diff --git a/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
index 70d1a5c08cc..f4fc6893520 100644
--- a/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
@@ -1,5 +1,5 @@
<script>
-import ciIcon from '~/vue_shared/components/ci_icon.vue';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
/**
* Component that renders both the CI icon status and the job name.
@@ -9,7 +9,7 @@ import ciIcon from '~/vue_shared/components/ci_icon.vue';
*/
export default {
components: {
- ciIcon,
+ CiIcon,
},
props: {
name: {
diff --git a/app/assets/javascripts/pipelines/components/performance_insights_modal.vue b/app/assets/javascripts/pipelines/components/performance_insights_modal.vue
deleted file mode 100644
index fdbf0ca19bc..00000000000
--- a/app/assets/javascripts/pipelines/components/performance_insights_modal.vue
+++ /dev/null
@@ -1,171 +0,0 @@
-<script>
-import { GlAlert, GlCard, GlLink, GlLoadingIcon, GlModal } from '@gitlab/ui';
-import { __, s__ } from '~/locale';
-import { humanizeTimeInterval } from '~/lib/utils/datetime_utility';
-import HelpPopover from '~/vue_shared/components/help_popover.vue';
-import getPerformanceInsightsQuery from '../graphql/queries/get_performance_insights.query.graphql';
-import { performanceModalId } from '../constants';
-import { calculateJobStats, calculateSlowestFiveJobs } from '../utils';
-
-export default {
- name: 'PerformanceInsightsModal',
- i18n: {
- queuedCardHeader: s__('Pipeline|Longest queued job'),
- queuedCardHelp: s__(
- 'Pipeline|The longest queued job is the job that spent the longest time in the pending state, waiting to be picked up by a Runner',
- ),
- executedCardHeader: s__('Pipeline|Last executed job'),
- executedCardHelp: s__(
- 'Pipeline|The last executed job is the last job to start in the pipeline.',
- ),
- viewDependency: s__('Pipeline|View dependency'),
- slowJobsTitle: s__('Pipeline|Five slowest jobs'),
- feeback: __('Feedback issue'),
- insightsLimit: s__('Pipeline|Only able to show first 100 results'),
- },
- modal: {
- title: s__('Pipeline|Performance insights'),
- actionCancel: {
- text: __('Close'),
- attributes: {
- variant: 'confirm',
- },
- },
- },
- performanceModalId,
- components: {
- GlAlert,
- GlCard,
- GlLink,
- GlModal,
- GlLoadingIcon,
- HelpPopover,
- },
- inject: {
- pipelineIid: {
- default: '',
- },
- pipelineProjectPath: {
- default: '',
- },
- },
- apollo: {
- jobs: {
- query: getPerformanceInsightsQuery,
- variables() {
- return {
- fullPath: this.pipelineProjectPath,
- iid: this.pipelineIid,
- };
- },
- update(data) {
- return data.project?.pipeline?.jobs;
- },
- },
- },
- data() {
- return {
- jobs: null,
- };
- },
- computed: {
- longestQueuedJob() {
- return calculateJobStats(this.jobs, 'queuedDuration');
- },
- lastExecutedJob() {
- return calculateJobStats(this.jobs, 'startedAt');
- },
- slowestFiveJobs() {
- return calculateSlowestFiveJobs(this.jobs);
- },
- queuedDurationDisplay() {
- return humanizeTimeInterval(this.longestQueuedJob.queuedDuration);
- },
- showLimitMessage() {
- return this.jobs.pageInfo.hasNextPage;
- },
- },
-};
-</script>
-
-<template>
- <gl-modal
- :modal-id="$options.performanceModalId"
- :title="$options.modal.title"
- :action-cancel="$options.modal.actionCancel"
- >
- <gl-loading-icon v-if="$apollo.queries.jobs.loading" size="lg" />
-
- <template v-else>
- <gl-alert class="gl-mb-4" :dismissible="false">
- <p v-if="showLimitMessage" data-testid="limit-alert-text">
- {{ $options.i18n.insightsLimit }}
- </p>
- <gl-link href="https://gitlab.com/gitlab-org/gitlab/-/issues/365902" class="gl-mt-5">
- {{ $options.i18n.feeback }}
- </gl-link>
- </gl-alert>
-
- <div class="gl-display-flex gl-justify-content-space-between gl-mt-2 gl-mb-7">
- <gl-card class="gl-w-half gl-mr-7 gl-text-center">
- <template #header>
- <span class="gl-font-weight-bold">{{ $options.i18n.queuedCardHeader }}</span>
- <help-popover>
- {{ $options.i18n.queuedCardHelp }}
- </help-popover>
- </template>
- <div class="gl-display-flex gl-flex-direction-column">
- <span
- class="gl-font-weight-bold gl-font-size-h2 gl-mb-2"
- data-testid="insights-queued-card-data"
- >
- {{ queuedDurationDisplay }}
- </span>
- <gl-link
- :href="longestQueuedJob.detailedStatus.detailsPath"
- data-testid="insights-queued-card-link"
- >
- {{ longestQueuedJob.name }}
- </gl-link>
- </div>
- </gl-card>
- <gl-card class="gl-w-half gl-text-center" data-testid="insights-executed-card">
- <template #header>
- <span class="gl-font-weight-bold">{{ $options.i18n.executedCardHeader }}</span>
- <help-popover>
- {{ $options.i18n.executedCardHelp }}
- </help-popover>
- </template>
- <div class="gl-display-flex gl-flex-direction-column">
- <span
- class="gl-font-weight-bold gl-font-size-h2 gl-mb-2"
- data-testid="insights-executed-card-data"
- >
- {{ lastExecutedJob.name }}
- </span>
- <gl-link
- :href="lastExecutedJob.detailedStatus.detailsPath"
- data-testid="insights-executed-card-link"
- >
- {{ $options.i18n.viewDependency }}
- </gl-link>
- </div>
- </gl-card>
- </div>
-
- <div class="gl-mt-7">
- <span class="gl-font-weight-bold">{{ $options.i18n.slowJobsTitle }}</span>
- <div
- v-for="job in slowestFiveJobs"
- :key="job.name"
- class="gl-display-flex gl-justify-content-space-between gl-mb-3 gl-mt-3 gl-p-4 gl-border-t-1 gl-border-t-solid gl-border-b-0 gl-border-b-solid gl-border-gray-100"
- >
- <span data-testid="insights-slow-job-stage">{{ job.stage.name }}</span>
- <gl-link :href="job.detailedStatus.detailsPath" data-testid="insights-slow-job-link">{{
- job.name
- }}</gl-link>
- </div>
- </div>
- </template>
- </gl-modal>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
index 793e343a02a..3f1d7255a2b 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
@@ -1,9 +1,9 @@
<script>
-import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
export default {
components: {
- tooltipOnTruncate,
+ TooltipOnTruncate,
},
props: {
jobName: {
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue
index e485b38ce11..600832b7633 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue
@@ -1,10 +1,9 @@
<script>
-import { capitalize, escape } from 'lodash';
-import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
export default {
components: {
- tooltipOnTruncate,
+ TooltipOnTruncate,
},
props: {
stageName: {
@@ -12,17 +11,12 @@ export default {
required: true,
},
},
- computed: {
- formattedTitle() {
- return capitalize(escape(this.stageName));
- },
- },
};
</script>
<template>
<tooltip-on-truncate :title="stageName" truncate-target="child" placement="top">
<div class="gl-py-2 gl-text-truncate gl-font-weight-bold gl-w-20">
- {{ formattedTitle }}
+ {{ stageName }}
</div>
</tooltip-on-truncate>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/accessors/linked_pipelines_accessors.js b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/accessors/linked_pipelines_accessors.js
new file mode 100644
index 00000000000..1ca9e35c008
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/accessors/linked_pipelines_accessors.js
@@ -0,0 +1,14 @@
+import { get } from 'lodash';
+
+export const accessors = {
+ rest: {
+ detailedStatus: ['details', 'status'],
+ },
+ graphql: {
+ detailedStatus: 'detailedStatus',
+ },
+};
+
+export const accessValue = (pipeline, dataMethod, path) => {
+ return get(pipeline, accessors[dataMethod][path]);
+};
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/job_item.vue
index 670fa398536..211c5f117c7 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/job_item.vue
@@ -158,7 +158,7 @@ export default {
:href="detailsPath"
:title="tooltipText"
:class="jobClasses"
- class="js-pipeline-graph-job-link qa-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none"
+ class="js-pipeline-graph-job-link menu-item gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none"
data-testid="job-with-link"
@click.stop="hideTooltips"
@mouseout="hideTooltips"
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue
new file mode 100644
index 00000000000..a5c6dc98694
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue
@@ -0,0 +1,132 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { accessValue } from './accessors/linked_pipelines_accessors';
+/**
+ * Renders the upstream/downstream portions of the pipeline mini graph.
+ */
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ CiIcon,
+ },
+ inject: {
+ dataMethod: {
+ default: 'rest',
+ },
+ },
+ props: {
+ triggeredBy: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ triggered: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ pipelinePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ maxRenderedPipelines: 3,
+ };
+ },
+ computed: {
+ // Exactly one of these (triggeredBy and triggered) must be truthy. Never both. Never neither.
+ isUpstream() {
+ return Boolean(this.triggeredBy.length) && !this.triggered.length;
+ },
+ isDownstream() {
+ return !this.triggeredBy.length && Boolean(this.triggered.length);
+ },
+ linkedPipelines() {
+ return this.isUpstream ? this.triggeredBy : this.triggered;
+ },
+ totalPipelineCount() {
+ return this.linkedPipelines.length;
+ },
+ linkedPipelinesTrimmed() {
+ return this.totalPipelineCount > this.maxRenderedPipelines
+ ? this.linkedPipelines.slice(0, this.maxRenderedPipelines)
+ : this.linkedPipelines;
+ },
+ shouldRenderCounter() {
+ return this.isDownstream && this.linkedPipelines.length > this.maxRenderedPipelines;
+ },
+ counterLabel() {
+ return `+${this.linkedPipelines.length - this.maxRenderedPipelines}`;
+ },
+ counterTooltipText() {
+ return sprintf(s__('LinkedPipelines|%{counterLabel} more downstream pipelines'), {
+ counterLabel: this.counterLabel,
+ });
+ },
+ },
+ methods: {
+ pipelineTooltipText(pipeline) {
+ const { label } = accessValue(pipeline, this.dataMethod, 'detailedStatus');
+
+ return `${pipeline.project.name} - ${label}`;
+ },
+ pipelineStatus(pipeline) {
+ // detailedStatus is graphQL, details.status is REST
+ return pipeline?.detailedStatus || pipeline?.details?.status;
+ },
+ triggerButtonClass(pipeline) {
+ const { group } = accessValue(pipeline, this.dataMethod, 'detailedStatus');
+
+ return `ci-status-icon-${group}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <span
+ v-if="linkedPipelines"
+ :class="{
+ 'is-upstream': isUpstream,
+ 'is-downstream': isDownstream,
+ }"
+ class="linked-pipeline-mini-list gl-display-inline gl-vertical-align-middle"
+ >
+ <a
+ v-for="pipeline in linkedPipelinesTrimmed"
+ :key="pipeline.id"
+ v-gl-tooltip="{ title: pipelineTooltipText(pipeline) }"
+ :href="pipeline.path"
+ :class="triggerButtonClass(pipeline)"
+ class="linked-pipeline-mini-item gl-display-inline-block gl-h-6 gl-mr-2 gl-my-2 gl-rounded-full gl-vertical-align-middle"
+ data-testid="linked-pipeline-mini-item"
+ >
+ <ci-icon
+ is-borderless
+ is-interactive
+ css-classes="gl-rounded-full"
+ :size="24"
+ :status="pipelineStatus(pipeline)"
+ class="gl-align-items-center gl-border gl-display-inline-flex"
+ />
+ </a>
+
+ <a
+ v-if="shouldRenderCounter"
+ v-gl-tooltip="{ title: counterTooltipText }"
+ :title="counterTooltipText"
+ :href="pipelinePath"
+ class="gl-align-items-center gl-bg-gray-50 gl-display-inline-flex gl-font-sm gl-h-6 gl-justify-content-center gl-rounded-pill gl-text-decoration-none gl-text-gray-500 gl-w-7 linked-pipelines-counter linked-pipeline-mini-item"
+ data-testid="linked-pipeline-counter"
+ >
+ {{ counterLabel }}
+ </a>
+ </span>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
new file mode 100644
index 00000000000..993fa121d89
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue
@@ -0,0 +1,103 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import PipelineStages from './pipeline_stages.vue';
+import LinkedPipelinesMiniList from './linked_pipelines_mini_list.vue';
+/**
+ * Renders the pipeline mini graph.
+ */
+export default {
+ components: {
+ GlIcon,
+ LinkedPipelinesMiniList,
+ PipelineStages,
+ },
+ arrowStyles: [
+ 'arrow-icon gl-display-inline-block gl-mx-1 gl-text-gray-500 gl-vertical-align-middle!',
+ ],
+ props: {
+ downstreamPipelines: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ isMergeTrain: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pipelinePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ stages: {
+ type: Array,
+ required: true,
+ default: () => [],
+ },
+ stagesClass: {
+ type: [Array, Object, String],
+ required: false,
+ default: '',
+ },
+ updateDropdown: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ upstreamPipeline: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
+ },
+ computed: {
+ hasDownstreamPipelines() {
+ return Boolean(this.downstreamPipelines.length);
+ },
+ },
+ methods: {
+ onPipelineActionRequestComplete() {
+ this.$emit('pipelineActionRequestComplete');
+ },
+ },
+};
+</script>
+<template>
+ <div class="stage-cell" data-testid="pipeline-mini-graph">
+ <linked-pipelines-mini-list
+ v-if="upstreamPipeline"
+ :triggered-by="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
+ upstreamPipeline,
+ ] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
+ data-testid="pipeline-mini-graph-upstream"
+ />
+ <gl-icon
+ v-if="upstreamPipeline"
+ :class="$options.arrowStyles"
+ name="long-arrow"
+ data-testid="upstream-arrow-icon"
+ />
+ <pipeline-stages
+ :is-merge-train="isMergeTrain"
+ :stages="stages"
+ :update-dropdown="updateDropdown"
+ :stages-class="stagesClass"
+ data-testid="pipeline-stages"
+ @pipelineActionRequestComplete="onPipelineActionRequestComplete"
+ @miniGraphStageClick="$emit('miniGraphStageClick')"
+ />
+ <gl-icon
+ v-if="hasDownstreamPipelines"
+ :class="$options.arrowStyles"
+ name="long-arrow"
+ data-testid="downstream-arrow-icon"
+ />
+ <linked-pipelines-mini-list
+ v-if="hasDownstreamPipelines"
+ :triggered="downstreamPipelines"
+ :pipeline-path="pipelinePath"
+ data-testid="pipeline-mini-graph-downstream"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue
index d7e55d36ff6..a68797a7235 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stage.vue
@@ -77,6 +77,10 @@ export default {
this.isDropdownOpen = true;
this.isLoading = true;
this.fetchJobs();
+
+ // used for tracking and is separate from event hub
+ // to avoid complexity with mixin
+ this.$emit('miniGraphStageClick');
},
fetchJobs() {
axios
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue
index 05cb2ebb769..e965dc5e6b0 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_mini_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue
@@ -1,7 +1,7 @@
<script>
-import PipelineStage from '~/pipelines/components/pipelines_list/pipeline_stage.vue';
+import PipelineStage from './pipeline_stage.vue';
/**
- * Renders the pipeline mini graph.
+ * Renders the pipeline stages portion of the pipeline mini graph.
*/
export default {
components: {
@@ -36,7 +36,7 @@ export default {
};
</script>
<template>
- <div data-testid="pipeline-mini-graph" class="gl-display-inline gl-vertical-align-middle">
+ <div data-testid="pipeline-stages" class="gl-display-inline gl-vertical-align-middle">
<div
v-for="stage in stages"
:key="stage.name"
@@ -48,6 +48,7 @@ export default {
:update-dropdown="updateDropdown"
:is-merge-train="isMergeTrain"
@pipelineActionRequestComplete="onPipelineActionRequestComplete"
+ @miniGraphStageClick="$emit('miniGraphStageClick')"
/>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
index 05a1ceface3..2d2f649f651 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
@@ -10,6 +10,8 @@ import {
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import axios from '~/lib/utils/axios_utils';
import { __, s__ } from '~/locale';
+import Tracking from '~/tracking';
+import { TRACKING_CATEGORIES } from '../../constants';
export const i18n = {
downloadArtifacts: __('Download artifacts'),
@@ -29,6 +31,7 @@ export default {
GlSearchBoxByType,
GlLoadingIcon,
},
+ mixins: [Tracking.mixin()],
inject: {
artifactsEndpoint: {
default: '',
@@ -60,6 +63,10 @@ export default {
},
methods: {
fetchArtifacts() {
+ // refactor tracking based on action once this dropdown supports
+ // actions other than artifacts
+ this.track('click_artifacts_dropdown', { label: TRACKING_CATEGORIES.table });
+
this.isLoading = true;
// Replace the placeholder with the ID of the pipeline we are viewing
const endpoint = this.artifactsEndpoint.replace(
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
index 7a08dacb824..dd62ffb27f7 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_operations.vue
@@ -1,7 +1,8 @@
<script>
import { GlButton, GlTooltipDirective, GlModalDirective } from '@gitlab/ui';
+import Tracking from '~/tracking';
import eventHub from '../../event_hub';
-import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL } from '../../constants';
+import { BUTTON_TOOLTIP_RETRY, BUTTON_TOOLTIP_CANCEL, TRACKING_CATEGORIES } from '../../constants';
import PipelineMultiActions from './pipeline_multi_actions.vue';
import PipelinesManualActions from './pipelines_manual_actions.vue';
@@ -17,6 +18,7 @@ export default {
PipelineMultiActions,
PipelinesManualActions,
},
+ mixins: [Tracking.mixin()],
props: {
pipeline: {
type: Object,
@@ -52,6 +54,7 @@ export default {
},
methods: {
handleCancelClick() {
+ this.trackClick('click_cancel_button');
eventHub.$emit('openConfirmationModal', {
pipeline: this.pipeline,
endpoint: this.pipeline.cancel_path,
@@ -59,8 +62,12 @@ export default {
},
handleRetryClick() {
this.isRetrying = true;
+ this.trackClick('click_retry_button');
eventHub.$emit('retryPipeline', this.pipeline.retry_path);
},
+ trackClick(action) {
+ this.track(action, { label: TRACKING_CATEGORIES.table });
+ },
},
};
</script>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
index ef21673115e..eb70b5fbb7a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
@@ -83,9 +83,7 @@ export default {
<span class="font-weight-bold">{{ __('Pipeline') }}</span>
- <a :href="pipeline.path" class="js-pipeline-path link-commit qa-pipeline-path"
- >#{{ pipeline.id }}</a
- >
+ <a :href="pipeline.path" class="js-pipeline-path link-commit">#{{ pipeline.id }}</a>
<template v-if="hasRef">
{{ __('from') }}
<a :href="pipeline.ref.path" class="link-commit ref-name">{{ pipeline.ref.name }}</a>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
index 09d588aaafd..39d41415456 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue
@@ -1,9 +1,10 @@
<script>
import { GlIcon, GlLink, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
+import Tracking from '~/tracking';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import { ICONS } from '../../constants';
+import { ICONS, TRACKING_CATEGORIES } from '../../constants';
import PipelineLabels from './pipeline_labels.vue';
export default {
@@ -17,6 +18,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [Tracking.mixin()],
props: {
pipeline: {
type: Object,
@@ -114,6 +116,11 @@ export default {
return this.pipeline?.commit?.title;
},
},
+ methods: {
+ trackClick(action) {
+ this.track(action, { label: TRACKING_CATEGORIES.table });
+ },
+ },
};
</script>
<template>
@@ -125,6 +132,7 @@ export default {
:href="commitUrl"
class="commit-row-message gl-text-gray-900"
data-testid="commit-title"
+ @click="trackClick('click_commit_title')"
>{{ commitTitle }}</gl-link
>
</tooltip-on-truncate>
@@ -137,6 +145,7 @@ export default {
class="gl-text-decoration-underline gl-text-blue-600! gl-mr-3"
data-testid="pipeline-url-link"
data-qa-selector="pipeline_url_link"
+ @click="trackClick('click_pipeline_id')"
>#{{ pipeline[pipelineKey] }}</gl-link
>
<!--Commit row-->
@@ -154,11 +163,17 @@ export default {
:href="mergeRequestRef.path"
class="ref-name gl-mr-3"
data-testid="merge-request-ref"
+ @click="trackClick('click_mr_ref')"
>{{ mergeRequestRef.iid }}</gl-link
>
- <gl-link v-else :href="refUrl" class="ref-name gl-mr-3" data-testid="commit-ref-name">{{
- commitRef.name
- }}</gl-link>
+ <gl-link
+ v-else
+ :href="refUrl"
+ class="ref-name gl-mr-3"
+ data-testid="commit-ref-name"
+ @click="trackClick('click_commit_name')"
+ >{{ commitRef.name }}</gl-link
+ >
</tooltip-on-truncate>
<gl-icon
v-gl-tooltip
@@ -167,9 +182,13 @@ export default {
:title="__('Commit')"
data-testid="commit-icon"
/>
- <gl-link :href="commitUrl" class="commit-sha mr-0" data-testid="commit-short-sha">{{
- commitShortSha
- }}</gl-link>
+ <gl-link
+ :href="commitUrl"
+ class="commit-sha mr-0"
+ data-testid="commit-short-sha"
+ @click="trackClick('click_commit_sha')"
+ >{{ commitShortSha }}</gl-link
+ >
<user-avatar-link
v-if="commitAuthor"
:link-href="commitAuthor.path"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index 485e338f639..f9022be888a 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -4,6 +4,7 @@ import { isEqual } from 'lodash';
import createFlash from '~/flash';
import { getParameterByName } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
+import Tracking from '~/tracking';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
import {
@@ -11,6 +12,7 @@ import {
RAW_TEXT_WARNING,
FILTER_TAG_IDENTIFIER,
PipelineKeyOptions,
+ TRACKING_CATEGORIES,
} from '../../constants';
import PipelinesMixin from '../../mixins/pipelines_mixin';
import PipelinesService from '../../services/pipelines_service';
@@ -35,7 +37,7 @@ export default {
PipelinesTableComponent,
TablePagination,
},
- mixins: [PipelinesMixin],
+ mixins: [PipelinesMixin, Tracking.mixin()],
props: {
store: {
type: Object,
@@ -246,6 +248,8 @@ export default {
params = this.onChangeWithFilter(params);
this.updateContent(params);
+
+ this.track('click_filter_tabs', { label: TRACKING_CATEGORIES.tabs });
},
successCallback(resp) {
// Because we are polling & the user is interacting verify if the response received
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
index 4d28545a035..af089aebbbe 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue
@@ -2,7 +2,9 @@
import { GlFilteredSearch } from '@gitlab/ui';
import { map } from 'lodash';
import { s__ } from '~/locale';
+import Tracking from '~/tracking';
import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { TRACKING_CATEGORIES } from '../../constants';
import PipelineBranchNameToken from './tokens/pipeline_branch_name_token.vue';
import PipelineSourceToken from './tokens/pipeline_source_token.vue';
import PipelineStatusToken from './tokens/pipeline_status_token.vue';
@@ -19,6 +21,7 @@ export default {
components: {
GlFilteredSearch,
},
+ mixins: [Tracking.mixin()],
props: {
projectId: {
type: String,
@@ -110,6 +113,7 @@ export default {
},
methods: {
onSubmit(filters) {
+ this.track('click_filtered_search', { label: TRACKING_CATEGORIES.search });
this.$emit('filterPipelines', filters);
},
},
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
index 47fffa8a6b2..16a747f6165 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_manual_actions.vue
@@ -4,8 +4,10 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { s__, __, sprintf } from '~/locale';
+import Tracking from '~/tracking';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
import eventHub from '../../event_hub';
+import { TRACKING_CATEGORIES } from '../../constants';
export default {
directives: {
@@ -17,6 +19,7 @@ export default {
GlDropdownItem,
GlIcon,
},
+ mixins: [Tracking.mixin()],
props: {
actions: {
type: Array,
@@ -66,7 +69,6 @@ export default {
createFlash({ message: __('An error occurred while making the request.') });
});
},
-
isActionDisabled(action) {
if (action.playable === undefined) {
return false;
@@ -74,6 +76,9 @@ export default {
return !action.playable;
},
+ trackClick() {
+ this.track('click_manual_actions', { label: TRACKING_CATEGORIES.table });
+ },
},
};
</script>
@@ -86,6 +91,7 @@ export default {
right
lazy
icon="play"
+ @shown="trackClick"
>
<gl-dropdown-item
v-for="action in actions"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
index e765a8cd86c..936ae4da1ec 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_status_badge.vue
@@ -1,6 +1,7 @@
<script>
-import { CHILD_VIEW } from '~/pipelines/constants';
+import { CHILD_VIEW, TRACKING_CATEGORIES } from '~/pipelines/constants';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
+import Tracking from '~/tracking';
import PipelinesTimeago from './time_ago.vue';
export default {
@@ -8,6 +9,7 @@ export default {
CiBadge,
PipelinesTimeago,
},
+ mixins: [Tracking.mixin()],
props: {
pipeline: {
type: Object,
@@ -26,6 +28,11 @@ export default {
return this.viewType === CHILD_VIEW;
},
},
+ methods: {
+ trackClick() {
+ this.track('click_ci_status_badge', { label: TRACKING_CATEGORIES.table });
+ },
+ },
};
</script>
@@ -37,6 +44,7 @@ export default {
:show-text="!isChildView"
:icon-classes="'gl-vertical-align-middle!'"
data-qa-selector="pipeline_commit_status"
+ @ciStatusBadgeClick="trackClick"
/>
<pipelines-timeago class="gl-mt-3" :pipeline="pipeline" />
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
index 53da98434b0..f6e46c090d3 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table.vue
@@ -1,8 +1,10 @@
<script>
import { GlTableLite, GlTooltipDirective } from '@gitlab/ui';
import { s__, __ } from '~/locale';
+import Tracking from '~/tracking';
+import PipelineMiniGraph from '~/pipelines/components/pipeline_mini_graph/pipeline_mini_graph.vue';
import eventHub from '../../event_hub';
-import PipelineMiniGraph from './pipeline_mini_graph.vue';
+import { TRACKING_CATEGORIES } from '../../constants';
import PipelineOperations from './pipeline_operations.vue';
import PipelineStopModal from './pipeline_stop_modal.vue';
import PipelineTriggerer from './pipeline_triggerer.vue';
@@ -17,8 +19,6 @@ const DEFAULT_TH_CLASSES =
export default {
components: {
GlTableLite,
- LinkedPipelinesMiniList: () =>
- import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'),
PipelineMiniGraph,
PipelineOperations,
PipelinesStatusBadge,
@@ -70,6 +70,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
+ mixins: [Tracking.mixin()],
props: {
pipelines: {
type: Array,
@@ -126,6 +127,9 @@ export default {
onPipelineActionRequestComplete() {
eventHub.$emit('refreshPipelinesTable');
},
+ trackPipelineMiniGraph() {
+ this.track('click_minigraph', { label: TRACKING_CATEGORIES.table });
+ },
},
TBODY_TR_ATTR: {
'data-testid': 'pipeline-table-row',
@@ -169,29 +173,15 @@ export default {
</template>
<template #cell(stages)="{ item }">
- <div class="stage-cell">
- <!-- This empty div should be removed, see https://gitlab.com/gitlab-org/gitlab/-/issues/323488 -->
- <div></div>
- <linked-pipelines-mini-list
- v-if="item.triggered_by"
- :triggered-by="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
- item.triggered_by,
- ] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
- data-testid="mini-graph-upstream"
- />
- <pipeline-mini-graph
- v-if="item.details && item.details.stages && item.details.stages.length > 0"
- :stages="item.details.stages"
- :update-dropdown="updateGraphDropdown"
- @pipelineActionRequestComplete="onPipelineActionRequestComplete"
- />
- <linked-pipelines-mini-list
- v-if="item.triggered.length"
- :triggered="item.triggered"
- :pipeline-path="item.path"
- data-testid="mini-graph-downstream"
- />
- </div>
+ <pipeline-mini-graph
+ :downstream-pipelines="item.triggered"
+ :pipeline-path="item.path"
+ :stages="item.details.stages"
+ :update-dropdown="updateGraphDropdown"
+ :upstream-pipeline="item.triggered_by"
+ @pipelineActionRequestComplete="onPipelineActionRequestComplete"
+ @miniGraphStageClick="trackPipelineMiniGraph"
+ />
</template>
<template #cell(actions)="{ item }">
diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js
index 7b38f870cb6..327633dcb1a 100644
--- a/app/assets/javascripts/pipelines/constants.js
+++ b/app/assets/javascripts/pipelines/constants.js
@@ -110,4 +110,8 @@ export const DEFAULT_FIELDS = [
},
];
-export const performanceModalId = 'performanceInsightsModal';
+export const TRACKING_CATEGORIES = {
+ table: 'pipelines_table_component',
+ tabs: 'pipelines_filter_tabs',
+ search: 'pipelines_filtered_search',
+};
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_performance_insights.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_performance_insights.query.graphql
deleted file mode 100644
index 25e990c8934..00000000000
--- a/app/assets/javascripts/pipelines/graphql/queries/get_performance_insights.query.graphql
+++ /dev/null
@@ -1,28 +0,0 @@
-query getPerformanceInsightsData($fullPath: ID!, $iid: ID!) {
- project(fullPath: $fullPath) {
- id
- pipeline(iid: $iid) {
- id
- jobs {
- pageInfo {
- hasNextPage
- }
- nodes {
- id
- duration
- detailedStatus {
- id
- detailsPath
- }
- name
- stage {
- id
- name
- }
- startedAt
- queuedDuration
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql
index 641ec7a3cf6..b0f875160d4 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql
@@ -11,6 +11,7 @@ query getPipelineJobs($fullPath: ID!, $iid: ID!, $after: String) {
}
nodes {
artifacts {
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
downloadPath
fileType
diff --git a/app/assets/javascripts/pipelines/pipeline_details_header.js b/app/assets/javascripts/pipelines/pipeline_details_header.js
index 2fedd7e7a98..c9e60756407 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_header.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_header.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
-import pipelineHeader from './components/header_component.vue';
+import PipelineHeader from './components/header_component.vue';
Vue.use(VueApollo);
@@ -16,7 +16,7 @@ export const createPipelineHeaderApp = (elSelector, apolloProvider, graphqlResou
new Vue({
el,
components: {
- pipelineHeader,
+ PipelineHeader,
},
apolloProvider,
provide: {
diff --git a/app/assets/javascripts/pipelines/pipeline_tabs.js b/app/assets/javascripts/pipelines/pipeline_tabs.js
index 7051d356089..508f188c229 100644
--- a/app/assets/javascripts/pipelines/pipeline_tabs.js
+++ b/app/assets/javascripts/pipelines/pipeline_tabs.js
@@ -20,6 +20,8 @@ export const createAppOptions = (selector, apolloProvider) => {
const {
canGenerateCodequalityReports,
codequalityReportDownloadPath,
+ codequalityBlobPath,
+ codequalityProjectPath,
downloadablePathForReportType,
exposeSecurityDashboard,
exposeLicenseScanningData,
@@ -40,9 +42,12 @@ export const createAppOptions = (selector, apolloProvider) => {
hasTestReport,
emptyStateImagePath,
artifactsExpiredImagePath,
+ isFullCodequalityReportAvailable,
testsCount,
} = dataset;
+ // TODO remove projectPath variable once https://gitlab.com/gitlab-org/gitlab/-/issues/371641 is resolved
+ const projectPath = fullPath;
const defaultTabValue = getPipelineDefaultTab(window.location.href);
return {
@@ -63,6 +68,10 @@ export const createAppOptions = (selector, apolloProvider) => {
provide: {
canGenerateCodequalityReports: parseBoolean(canGenerateCodequalityReports),
codequalityReportDownloadPath,
+ codequalityBlobPath,
+ codequalityProjectPath,
+ isFullCodequalityReportAvailable: parseBoolean(isFullCodequalityReportAvailable),
+ projectPath,
defaultTabValue,
downloadablePathForReportType,
exposeSecurityDashboard: parseBoolean(exposeSecurityDashboard),
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 83e00b80426..588d15495ab 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -153,24 +153,3 @@ export const getPipelineDefaultTab = (url) => {
return null;
};
-
-export const calculateJobStats = (jobs, sortField) => {
- const jobNodes = [...jobs.nodes];
-
- const sorted = jobNodes.sort((a, b) => {
- return b[sortField] - a[sortField];
- });
-
- return sorted[0];
-};
-
-export const calculateSlowestFiveJobs = (jobs) => {
- const jobNodes = [...jobs.nodes];
- const limit = 5;
-
- return jobNodes
- .sort((a, b) => {
- return b.duration - a.duration;
- })
- .slice(0, limit);
-};