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:
Diffstat (limited to 'app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue')
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue164
1 files changed, 164 insertions, 0 deletions
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue
new file mode 100644
index 00000000000..6b5e3d77b92
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/failed_job_details.vue
@@ -0,0 +1,164 @@
+<script>
+import { GlButton, GlCollapse, GlIcon, GlLink, GlTooltip } from '@gitlab/ui';
+import { createAlert } from '~/alert';
+import { __, s__, sprintf } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+import RetryMrFailedJobMutation from '../../../graphql/mutations/retry_mr_failed_job.mutation.graphql';
+
+export default {
+ components: {
+ CiIcon,
+ GlButton,
+ GlCollapse,
+ GlIcon,
+ GlLink,
+ GlTooltip,
+ },
+ directives: {
+ SafeHtml,
+ },
+ props: {
+ job: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isHovered: false,
+ isJobLogVisible: false,
+ isLoadingAction: false,
+ };
+ },
+ computed: {
+ activeClass() {
+ return this.isHovered ? 'gl-bg-gray-50' : '';
+ },
+ canReadBuild() {
+ return this.job.userPermissions.readBuild;
+ },
+ canRetryJob() {
+ return this.job.retryable && this.job.userPermissions.updateBuild;
+ },
+ isVisibleId() {
+ return `log-${this.isJobLogVisible ? 'is-visible' : 'is-hidden'}`;
+ },
+ jobChevronName() {
+ return this.isJobLogVisible ? 'chevron-down' : 'chevron-right';
+ },
+ jobTrace() {
+ if (this.canReadBuild) {
+ return this.job?.trace?.htmlSummary || this.$options.i18n.noTraceText;
+ }
+
+ return this.$options.i18n.cannotReadBuild;
+ },
+ parsedJobId() {
+ return getIdFromGraphQLId(this.job.id);
+ },
+ tooltipText() {
+ return sprintf(this.$options.i18n.jobActionTooltipText, { jobName: this.job.name });
+ },
+ },
+ methods: {
+ setActiveRow() {
+ this.isHovered = true;
+ },
+ resetActiveRow() {
+ this.isHovered = false;
+ },
+ async retryJob() {
+ try {
+ this.isLoadingAction = true;
+
+ const {
+ data: {
+ jobRetry: { errors },
+ },
+ } = await this.$apollo.mutate({
+ mutation: RetryMrFailedJobMutation,
+ variables: { id: this.job.id },
+ });
+
+ if (errors.length > 0) {
+ throw new Error(errors[0]);
+ }
+
+ this.$emit('job-retried', this.job.name);
+ } catch (error) {
+ createAlert({ message: error?.message || this.$options.i18n.retryError });
+ } finally {
+ this.isLoadingAction = false;
+ }
+ },
+ toggleJobLog(event) {
+ // Do not toggle the log visibility when clicking on a link
+ if (event.target.tagName === 'A') {
+ return;
+ }
+ this.isJobLogVisible = !this.isJobLogVisible;
+ },
+ },
+ i18n: {
+ cannotReadBuild: s__("Job|You do not have permission to read this job's log"),
+ cannotRetry: s__('Job|You do not have permission to retry this job'),
+ jobActionTooltipText: s__('Pipelines|Retry %{jobName} Job'),
+ noTraceText: s__('Job|No job log'),
+ retry: __('Retry'),
+ retryError: __('There was an error while retrying this job'),
+ },
+};
+</script>
+<template>
+ <div class="container-fluid gl-grid-tpl-rows-auto">
+ <div
+ class="row gl-py-4 gl-cursor-pointer gl-display-flex gl-align-items-center"
+ :class="activeClass"
+ :aria-pressed="isJobLogVisible"
+ role="button"
+ tabindex="0"
+ data-testid="widget-row"
+ @click="toggleJobLog"
+ @keyup.enter="toggleJobLog"
+ @keyup.space="toggleJobLog"
+ @mouseover="setActiveRow"
+ @mouseout="resetActiveRow"
+ >
+ <div class="col-6 gl-text-gray-900 gl-font-weight-bold gl-text-left">
+ <gl-icon :name="jobChevronName" class="gl-fill-blue-500" />
+ <ci-icon :status="job.detailedStatus" />
+ {{ job.name }}
+ </div>
+ <div class="col-2 gl-text-left">{{ job.stage.name }}</div>
+ <div class="col-2 gl-text-left">
+ <gl-link :href="job.webPath">#{{ parsedJobId }}</gl-link>
+ </div>
+ <gl-tooltip v-if="!canRetryJob" :target="() => $refs.retryBtn" placement="top">
+ {{ $options.i18n.cannotRetry }}
+ </gl-tooltip>
+ <div class="col-2 gl-text-left">
+ <span ref="retryBtn">
+ <gl-button
+ :disabled="!canRetryJob"
+ icon="retry"
+ :loading="isLoadingAction"
+ :title="$options.i18n.retry"
+ :aria-label="$options.i18n.retry"
+ @click.stop="retryJob"
+ />
+ </span>
+ </div>
+ </div>
+ <div class="row">
+ <gl-collapse :visible="isJobLogVisible" class="gl-w-full">
+ <pre
+ v-safe-html="jobTrace"
+ class="gl-bg-gray-900 gl-text-white"
+ :data-testid="isVisibleId"
+ ></pre>
+ </gl-collapse>
+ </div>
+ </div>
+</template>