Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-26 21:09:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-26 21:09:16 +0300
commit006a4f3c1c288c1ea59c3423225527897fa60d6e (patch)
treee4e0d2bb7de0b1ad82bd366088d007b9055d447a /app/assets
parent2446c39adaea91d1120c9eb0936e93e9314171c1 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue6
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue1
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue3
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue25
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/utils.js9
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/api.js2
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue3
-rw-r--r--app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue (renamed from app/assets/javascripts/pipelines/components/graph/action_component.vue)2
-rw-r--r--app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue (renamed from app/assets/javascripts/pipelines/components/graph/job_name_component.vue)0
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue186
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue2
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js2
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_graph.js2
-rw-r--r--app/assets/javascripts/pipelines/utils.js8
-rw-r--r--app/assets/javascripts/tracking.js8
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
26 files changed, 254 insertions, 42 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
index 6652c0026ca..fefa784f060 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_editor_header.vue
@@ -35,10 +35,14 @@ export default {
type: Object,
required: true,
},
+ isNewCiConfigFile: {
+ type: Boolean,
+ required: true,
+ },
},
computed: {
showPipelineStatus() {
- return this.glFeatures.pipelineStatusForPipelineEditor;
+ return this.glFeatures.pipelineStatusForPipelineEditor && !this.isNewCiConfigFile;
},
// make sure corners are rounded correctly depending on if
// pipeline status is rendered
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 488cabc85be..bd1853d3bab 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -278,6 +278,7 @@ export default {
<pipeline-editor-home
:ci-config-data="ciConfigData"
:ci-file-content="currentCiFileContent"
+ :is-new-ci-config-file="isNewCiConfigFile"
@commit="updateOnCommit"
@resetContent="resetContent"
@showError="showErrorAlert"
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
index 0eba8696f7b..aafd95412c4 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_home.vue
@@ -19,6 +19,10 @@ export default {
type: String,
required: true,
},
+ isNewCiConfigFile: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
return {
@@ -40,7 +44,10 @@ export default {
<template>
<div>
- <pipeline-editor-header :ci-config-data="ciConfigData" />
+ <pipeline-editor-header
+ :ci-config-data="ciConfigData"
+ :is-new-ci-config-file="isNewCiConfigFile"
+ />
<pipeline-editor-tabs
:ci-config-data="ciConfigData"
:ci-file-content="ciFileContent"
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 363226a0d85..d7a7fc9c375 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,10 +1,11 @@
<script>
+import { reportToSentry } from '../../utils';
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
import LinksLayer from '../graph_shared/links_layer.vue';
import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH } from './constants';
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import StageColumnComponent from './stage_column_component.vue';
-import { reportToSentry, validateConfigPaths } from './utils';
+import { validateConfigPaths } from './utils';
export default {
name: 'PipelineGraph',
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
index abbf8df6eed..39d0fa8a8ca 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_legacy.vue
@@ -2,10 +2,10 @@
import { GlLoadingIcon } from '@gitlab/ui';
import { escape, capitalize } from 'lodash';
import GraphBundleMixin from '../../mixins/graph_pipeline_bundle_mixin';
+import { reportToSentry } from '../../utils';
import { UPSTREAM, DOWNSTREAM, MAIN } from './constants';
import LinkedPipelinesColumnLegacy from './linked_pipelines_column_legacy.vue';
import StageColumnComponentLegacy from './stage_column_component_legacy.vue';
-import { reportToSentry } from './utils';
export default {
name: 'PipelineGraphLegacy',
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 5299694ce13..be0f3643784 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
@@ -4,12 +4,12 @@ import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.qu
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { DEFAULT, DRAW_FAILURE, LOAD_FAILURE } from '../../constants';
+import { reportToSentry } from '../../utils';
import { IID_FAILURE, STAGE_VIEW } from './constants';
import PipelineGraph from './graph_component.vue';
import GraphViewSelector from './graph_view_selector.vue';
import {
getQueryHeaders,
- reportToSentry,
serializeLoadErrors,
toggleQueryPollingByVisibility,
unwrapPipelineData,
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 f6aee8c5fcf..8577a49ff7a 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -1,8 +1,8 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { reportToSentry } from '../../utils';
import JobItem from './job_item.vue';
-import { reportToSentry } from './utils';
/**
* Renders the dropdown for the pipeline graph.
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 46ef0457d40..df83488a226 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -3,11 +3,11 @@ import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { sprintf } from '~/locale';
+import { reportToSentry } from '../../utils';
+import ActionComponent from '../jobs_shared/action_component.vue';
+import JobNameComponent from '../jobs_shared/job_name_component.vue';
import { accessValue } from './accessors';
-import ActionComponent from './action_component.vue';
import { REST } from './constants';
-import JobNameComponent from './job_name_component.vue';
-import { reportToSentry } from './utils';
/**
* Renders the badge for the pipeline graph and the job's dropdown.
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index add7b3445f7..5fc3988ed29 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -3,9 +3,9 @@ import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon, GlBadge } from '@g
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
+import { reportToSentry } from '../../utils';
import { accessValue } from './accessors';
import { DOWNSTREAM, REST, UPSTREAM } from './constants';
-import { reportToSentry } from './utils';
export default {
directives: {
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
index b55a77a3c4f..a8942c86ba9 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -1,11 +1,11 @@
<script>
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
import { LOAD_FAILURE } from '../../constants';
+import { reportToSentry } from '../../utils';
import { ONE_COL_WIDTH, UPSTREAM } from './constants';
import LinkedPipeline from './linked_pipeline.vue';
import {
getQueryHeaders,
- reportToSentry,
serializeLoadErrors,
toggleQueryPollingByVisibility,
unwrapPipelineData,
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
index 0d1ff94c275..39baeb6e1c3 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column_legacy.vue
@@ -1,7 +1,7 @@
<script>
+import { reportToSentry } from '../../utils';
import { UPSTREAM } from './constants';
import LinkedPipeline from './linked_pipeline.vue';
-import { reportToSentry } from './utils';
export default {
components: {
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 66467dbc994..0e945a553e4 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -1,13 +1,13 @@
<script>
import { capitalize, 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';
+import ActionComponent from '../jobs_shared/action_component.vue';
import { accessValue } from './accessors';
-import ActionComponent from './action_component.vue';
import { GRAPHQL } from './constants';
import JobGroupDropdown from './job_group_dropdown.vue';
import JobItem from './job_item.vue';
-import { reportToSentry } from './utils';
export default {
components: {
@@ -97,6 +97,23 @@ export default {
isFadedOut(jobName) {
return this.highlightedJobs.length > 1 && !this.highlightedJobs.includes(jobName);
},
+ isParallel(group) {
+ return group.size > 1 && group.jobs.length > 1;
+ },
+ singleJobExists(group) {
+ const firstJobDefined = Boolean(group.jobs?.[0]);
+
+ if (!firstJobDefined) {
+ const currentGroup = this.groups.find((element) => element.name === group.name);
+ const serializedGroup = Object.entries(currentGroup).join(' ');
+ reportToSentry(
+ 'stage_column_component',
+ `undefined_job_hunt, serialized group: ${serializedGroup}`,
+ );
+ }
+
+ return group.size === 1 && firstJobDefined;
+ },
},
};
</script>
@@ -130,7 +147,7 @@ export default {
@mouseleave="$emit('jobHover', '')"
>
<job-item
- v-if="group.size === 1"
+ v-if="singleJobExists(group)"
:job="group.jobs[0]"
:job-hovered="jobHovered"
:pipeline-expanded="pipelineExpanded"
@@ -139,7 +156,7 @@ export default {
:class="{ 'gl-opacity-3': isFadedOut(group.name) }"
@pipelineActionRequestComplete="$emit('refreshPipelineGraph')"
/>
- <div v-else :class="{ 'gl-opacity-3': isFadedOut(group.name) }">
+ <div v-else-if="isParallel(group)" :class="{ 'gl-opacity-3': isFadedOut(group.name) }">
<job-group-dropdown :group="group" :pipeline-id="pipelineId" />
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
index 2cee2fbbd8f..cbaf07c05cf 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component_legacy.vue
@@ -1,10 +1,10 @@
<script>
import { isEmpty, escape } from 'lodash';
import stageColumnMixin from '../../mixins/stage_column_mixin';
-import ActionComponent from './action_component.vue';
+import { reportToSentry } from '../../utils';
+import ActionComponent from '../jobs_shared/action_component.vue';
import JobGroupDropdown from './job_group_dropdown.vue';
import JobItem from './job_item.vue';
-import { reportToSentry } from './utils';
export default {
components: {
diff --git a/app/assets/javascripts/pipelines/components/graph/utils.js b/app/assets/javascripts/pipelines/components/graph/utils.js
index b9a8e2638bc..d36f18f0903 100644
--- a/app/assets/javascripts/pipelines/components/graph/utils.js
+++ b/app/assets/javascripts/pipelines/components/graph/utils.js
@@ -1,4 +1,3 @@
-import * as Sentry from '@sentry/browser';
import Visibility from 'visibilityjs';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { unwrapStagesWithNeeds } from '../unwrapping_utils';
@@ -24,13 +23,6 @@ const getQueryHeaders = (etagResource) => {
};
};
-const reportToSentry = (component, failureType) => {
- Sentry.withScope((scope) => {
- scope.setTag('component', component);
- Sentry.captureException(failureType);
- });
-};
-
const serializeGqlErr = (gqlError) => {
const { locations = [], message = '', path = [] } = gqlError;
@@ -113,7 +105,6 @@ const validateConfigPaths = (value) => value.graphqlResourceEtag?.length > 0;
export {
getQueryHeaders,
- reportToSentry,
serializeGqlErr,
serializeLoadErrors,
toggleQueryPollingByVisibility,
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/api.js b/app/assets/javascripts/pipelines/components/graph_shared/api.js
index 04ac15ae24c..49cd04d11e9 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/api.js
+++ b/app/assets/javascripts/pipelines/components/graph_shared/api.js
@@ -1,5 +1,5 @@
import axios from '~/lib/utils/axios_utils';
-import { reportToSentry } from '../graph/utils';
+import { reportToSentry } from '../../utils';
export const reportPerformance = (path, stats) => {
axios.post(path, stats).catch((err) => {
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
index fad57084992..382127285ba 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_inner.vue
@@ -10,8 +10,7 @@ import {
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
import { DRAW_FAILURE } from '../../constants';
-import { createJobsHash, generateJobNeedsDict } from '../../utils';
-import { reportToSentry } from '../graph/utils';
+import { createJobsHash, generateJobNeedsDict, reportToSentry } from '../../utils';
import { parseData } from '../parsing_utils';
import { reportPerformance } from './api';
import { generateLinksData } from './drawing_utils';
diff --git a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
index 42eab13b0bd..8dbab245f44 100644
--- a/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
+++ b/app/assets/javascripts/pipelines/components/graph_shared/links_layer.vue
@@ -11,7 +11,7 @@ import {
PIPELINES_DETAIL_LINKS_JOB_RATIO,
} from '~/performance/constants';
import { performanceMarkAndMeasure } from '~/performance/utils';
-import { reportToSentry } from '../graph/utils';
+import { reportToSentry } from '../../utils';
import { parseData } from '../parsing_utils';
import { reportPerformance } from './api';
import LinksInner from './links_inner.vue';
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
index 1df693704d4..3972c126673 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/action_component.vue
@@ -5,7 +5,7 @@ import axios from '~/lib/utils/axios_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
-import { reportToSentry } from './utils';
+import { reportToSentry } from '../../utils';
/**
* Renders either a cancel, retry or play icon button and handles the post request
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
index fffd8e1818a..fffd8e1818a 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/jobs_shared/job_name_component.vue
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue b/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue
new file mode 100644
index 00000000000..de326e3eeb6
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/job_item.vue
@@ -0,0 +1,186 @@
+<script>
+import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
+import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
+import { sprintf } from '~/locale';
+import { reportToSentry } from '../../utils';
+import ActionComponent from '../jobs_shared/action_component.vue';
+import JobNameComponent from '../jobs_shared/job_name_component.vue';
+
+/**
+ * Renders the badge for the pipeline graph and the job's dropdown.
+ *
+ * The following object should be provided as `job`:
+ *
+ * {
+ * "id": 4256,
+ * "name": "test",
+ * "status": {
+ * "icon": "status_success",
+ * "text": "passed",
+ * "label": "passed",
+ * "group": "success",
+ * "tooltip": "passed",
+ * "details_path": "/root/ci-mock/builds/4256",
+ * "action": {
+ * "icon": "retry",
+ * "title": "Retry",
+ * "path": "/root/ci-mock/builds/4256/retry",
+ * "method": "post"
+ * }
+ * }
+ * }
+ */
+
+export default {
+ hoverClass: 'gl-shadow-x0-y0-b3-s1-blue-500',
+ components: {
+ ActionComponent,
+ JobNameComponent,
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [delayedJobMixin],
+ props: {
+ job: {
+ type: Object,
+ required: true,
+ },
+ cssClassJobName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ dropdownLength: {
+ type: Number,
+ required: false,
+ default: Infinity,
+ },
+ jobHovered: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ pipelineExpanded: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ pipelineId: {
+ type: Number,
+ required: false,
+ default: -1,
+ },
+ },
+ computed: {
+ boundary() {
+ return this.dropdownLength === 1 ? 'viewport' : 'scrollParent';
+ },
+ detailsPath() {
+ return this.status.details_path;
+ },
+ hasDetails() {
+ return this.status.has_details;
+ },
+ status() {
+ return this.job && this.job.status ? this.job.status : {};
+ },
+ tooltipText() {
+ const textBuilder = [];
+ const { name: jobName } = this.job;
+
+ if (jobName) {
+ textBuilder.push(jobName);
+ }
+
+ const { tooltip: statusTooltip } = this.status;
+ if (jobName && statusTooltip) {
+ textBuilder.push('-');
+ }
+
+ if (statusTooltip) {
+ if (this.isDelayedJob) {
+ textBuilder.push(sprintf(statusTooltip, { remainingTime: this.remainingTime }));
+ } else {
+ textBuilder.push(statusTooltip);
+ }
+ }
+
+ return textBuilder.join(' ');
+ },
+ /**
+ * Verifies if the provided job has an action path
+ *
+ * @return {Boolean}
+ */
+ hasAction() {
+ return this.job.status && this.job.status.action && this.job.status.action.path;
+ },
+ relatedDownstreamHovered() {
+ return this.job.name === this.jobHovered;
+ },
+ relatedDownstreamExpanded() {
+ return this.job.name === this.pipelineExpanded.jobName && this.pipelineExpanded.expanded;
+ },
+ jobClasses() {
+ return this.relatedDownstreamHovered || this.relatedDownstreamExpanded
+ ? `${this.$options.hoverClass} ${this.cssClassJobName}`
+ : this.cssClassJobName;
+ },
+ },
+ errorCaptured(err, _vm, info) {
+ reportToSentry('pipelines_job_item', `pipelines_job_item error: ${err}, info: ${info}`);
+ },
+ methods: {
+ hideTooltips() {
+ this.$root.$emit(BV_HIDE_TOOLTIP);
+ },
+ pipelineActionRequestComplete() {
+ this.$emit('pipelineActionRequestComplete');
+ },
+ },
+};
+</script>
+<template>
+ <div
+ class="ci-job-component gl-display-flex gl-align-items-center gl-justify-content-space-between"
+ data-qa-selector="job_item_container"
+ >
+ <gl-link
+ v-if="hasDetails"
+ v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
+ :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"
+ data-testid="job-with-link"
+ @click.stop="hideTooltips"
+ @mouseout="hideTooltips"
+ >
+ <job-name-component :name="job.name" :status="job.status" :icon-size="24" />
+ </gl-link>
+
+ <div
+ v-else
+ v-gl-tooltip="{ boundary, placement: 'bottom', customClass: 'gl-pointer-events-none' }"
+ :title="tooltipText"
+ :class="jobClasses"
+ class="js-job-component-tooltip non-details-job-component menu-item"
+ data-testid="job-without-link"
+ @mouseout="hideTooltips"
+ >
+ <job-name-component :name="job.name" :status="job.status" :icon-size="24" />
+ </div>
+
+ <action-component
+ v-if="hasAction"
+ :tooltip-text="status.action.title"
+ :link="status.action.path"
+ :action-icon="status.action.icon"
+ data-qa-selector="action_button"
+ @pipelineActionRequestComplete="pipelineActionRequestComplete"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
index bdb7dd06620..d15c3e0bb6d 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
@@ -17,7 +17,7 @@ import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import eventHub from '../../event_hub';
-import JobItem from '../graph/job_item.vue';
+import JobItem from './job_item.vue';
export default {
components: {
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 6b2312edf75..849f4c27988 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -3,12 +3,12 @@ import { deprecatedCreateFlash as Flash } from '~/flash';
import { __ } from '~/locale';
import Translate from '~/vue_shared/translate';
import PipelineGraphLegacy from './components/graph/graph_component_legacy.vue';
-import { reportToSentry } from './components/graph/utils';
import TestReports from './components/test_reports/test_reports.vue';
import GraphBundleMixin from './mixins/graph_pipeline_bundle_mixin';
import createDagApp from './pipeline_details_dag';
import { apolloProvider } from './pipeline_shared_client';
import createTestReportsStore from './stores/test_reports';
+import { reportToSentry } from './utils';
Vue.use(Translate);
diff --git a/app/assets/javascripts/pipelines/pipeline_details_graph.js b/app/assets/javascripts/pipelines/pipeline_details_graph.js
index 453b387f2f3..39c3c2ea5c5 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_graph.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_graph.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { GRAPHQL } from './components/graph/constants';
import PipelineGraphWrapper from './components/graph/graph_component_wrapper.vue';
-import { reportToSentry } from './components/graph/utils';
+import { reportToSentry } from './utils';
Vue.use(VueApollo);
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 22820fca43e..0a6c326fa3d 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -1,3 +1,4 @@
+import * as Sentry from '@sentry/browser';
import { pickBy } from 'lodash';
import { createNodeDict } from './components/parsing_utils';
import { SUPPORTED_FILTER_PARAMETERS } from './constants';
@@ -65,3 +66,10 @@ export const generateJobNeedsDict = (jobs = {}) => {
return { ...acc, [value]: uniqueValues };
}, {});
};
+
+export const reportToSentry = (component, failureType) => {
+ Sentry.withScope((scope) => {
+ scope.setTag('component', component);
+ Sentry.captureException(failureType);
+ });
+};
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index 01de034417e..eccce0d857e 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -28,7 +28,7 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
};
const createEventPayload = (el, { suffix = '' } = {}) => {
- const action = el.dataset.trackEvent + (suffix || '');
+ const action = (el.dataset.trackAction || el.dataset.trackEvent) + (suffix || '');
let value = el.dataset.trackValue || el.value || undefined;
if (el.type === 'checkbox' && !el.checked) value = false;
@@ -52,7 +52,7 @@ const createEventPayload = (el, { suffix = '' } = {}) => {
};
const eventHandler = (e, func, opts = {}) => {
- const el = e.target.closest('[data-track-event]');
+ const el = e.target.closest('[data-track-event], [data-track-action]');
if (!el) return;
@@ -130,7 +130,9 @@ export default class Tracking {
static trackLoadEvents(category = document.body.dataset.page, parent = document) {
if (!this.enabled()) return [];
- const loadEvents = parent.querySelectorAll('[data-track-event="render"]');
+ const loadEvents = parent.querySelectorAll(
+ '[data-track-action="render"], [data-track-event="render"]',
+ );
loadEvents.forEach((element) => {
const { action, data } = createEventPayload(element);
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index f31b6d96f03..aa9ebfe2968 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -278,10 +278,6 @@
.card-header {
display: flex;
align-items: center;
-
- > .btn-success {
- margin-left: auto;
- }
}
.custom-metric {