BigW Consortium Gitlab

pipelines_table_row.vue 8.24 KB
<script>
/* eslint-disable no-param-reassign */
import asyncButtonComponent from './async_button.vue';
import pipelinesActionsComponent from './pipelines_actions.vue';
import pipelinesArtifactsComponent from './pipelines_artifacts.vue';
import ciBadge from '../../vue_shared/components/ci_badge_link.vue';
import pipelineStage from './stage.vue';
import pipelineUrl from './pipeline_url.vue';
import pipelinesTimeago from './time_ago.vue';
import commitComponent from '../../vue_shared/components/commit.vue';

/**
 * Pipeline table row.
 *
 * Given the received object renders a table row in the pipelines' table.
 */
export default {
  props: {
    pipeline: {
      type: Object,
      required: true,
    },
    updateGraphDropdown: {
      type: Boolean,
      required: false,
      default: false,
    },
  },
  components: {
    asyncButtonComponent,
    pipelinesActionsComponent,
    pipelinesArtifactsComponent,
    commitComponent,
    pipelineStage,
    pipelineUrl,
    ciBadge,
    pipelinesTimeago,
  },
  computed: {
    /**
     * If provided, returns the commit tag.
     * Needed to render the commit component column.
     *
     * This field needs a lot of verification, because of different possible cases:
     *
     * 1. person who is an author of a commit might be a GitLab user
     * 2. if person who is an author of a commit is a GitLab user he/she can have a GitLab avatar
     * 3. If GitLab user does not have avatar he/she might have a Gravatar
     * 4. If committer is not a GitLab User he/she can have a Gravatar
     * 5. We do not have consistent API object in this case
     * 6. We should improve API and the code
     *
     * @returns {Object|Undefined}
     */
    commitAuthor() {
      let commitAuthorInformation;

      if (!this.pipeline || !this.pipeline.commit) {
        return null;
      }

      // 1. person who is an author of a commit might be a GitLab user
      if (this.pipeline.commit.author) {
        // 2. if person who is an author of a commit is a GitLab user
        // he/she can have a GitLab avatar
        if (this.pipeline.commit.author.avatar_url) {
          commitAuthorInformation = this.pipeline.commit.author;

          // 3. If GitLab user does not have avatar he/she might have a Gravatar
        } else if (this.pipeline.commit.author_gravatar_url) {
          commitAuthorInformation = Object.assign({}, this.pipeline.commit.author, {
            avatar_url: this.pipeline.commit.author_gravatar_url,
          });
        }
        // 4. If committer is not a GitLab User he/she can have a Gravatar
      } else {
        commitAuthorInformation = {
          avatar_url: this.pipeline.commit.author_gravatar_url,
          path: `mailto:${this.pipeline.commit.author_email}`,
          username: this.pipeline.commit.author_name,
        };
      }

      return commitAuthorInformation;
    },

    /**
     * If provided, returns the commit tag.
     * Needed to render the commit component column.
     *
     * @returns {String|Undefined}
     */
    commitTag() {
      if (this.pipeline.ref &&
        this.pipeline.ref.tag) {
        return this.pipeline.ref.tag;
      }
      return undefined;
    },

    /**
     * If provided, returns the commit ref.
     * Needed to render the commit component column.
     *
     * Matches `path` prop sent in the API to `ref_url` prop needed
     * in the commit component.
     *
     * @returns {Object|Undefined}
     */
    commitRef() {
      if (this.pipeline.ref) {
        return Object.keys(this.pipeline.ref).reduce((accumulator, prop) => {
          if (prop === 'path') {
            accumulator.ref_url = this.pipeline.ref[prop];
          } else {
            accumulator[prop] = this.pipeline.ref[prop];
          }
          return accumulator;
        }, {});
      }

      return undefined;
    },

    /**
     * If provided, returns the commit url.
     * Needed to render the commit component column.
     *
     * @returns {String|Undefined}
     */
    commitUrl() {
      if (this.pipeline.commit &&
        this.pipeline.commit.commit_path) {
        return this.pipeline.commit.commit_path;
      }
      return undefined;
    },

    /**
     * If provided, returns the commit short sha.
     * Needed to render the commit component column.
     *
     * @returns {String|Undefined}
     */
    commitShortSha() {
      if (this.pipeline.commit &&
        this.pipeline.commit.short_id) {
        return this.pipeline.commit.short_id;
      }
      return undefined;
    },

    /**
     * If provided, returns the commit title.
     * Needed to render the commit component column.
     *
     * @returns {String|Undefined}
     */
    commitTitle() {
      if (this.pipeline.commit &&
        this.pipeline.commit.title) {
        return this.pipeline.commit.title;
      }
      return undefined;
    },

    /**
     * Timeago components expects a number
     *
     * @return {type}  description
     */
    pipelineDuration() {
      if (this.pipeline.details && this.pipeline.details.duration) {
        return this.pipeline.details.duration;
      }

      return 0;
    },

    /**
     * Timeago component expects a String.
     *
     * @return {String}
     */
    pipelineFinishedAt() {
      if (this.pipeline.details && this.pipeline.details.finished_at) {
        return this.pipeline.details.finished_at;
      }

      return '';
    },

    pipelineStatus() {
      if (this.pipeline.details && this.pipeline.details.status) {
        return this.pipeline.details.status;
      }
      return {};
    },

    displayPipelineActions() {
      return this.pipeline.flags.retryable ||
             this.pipeline.flags.cancelable ||
             this.pipeline.details.manual_actions.length ||
             this.pipeline.details.artifacts.length;
    },
  },
};
</script>
<template>
  <div class="commit gl-responsive-table-row">
    <div class="table-section section-10 commit-link">
      <div class="table-mobile-header"
        role="rowheader">
        Status
      </div>
      <div class="table-mobile-content">
        <ci-badge :status="pipelineStatus"/>
      </div>
    </div>

    <pipeline-url :pipeline="pipeline" />

    <div class="table-section section-25">
      <div
        class="table-mobile-header"
        role="rowheader">
        Commit
      </div>
      <div class="table-mobile-content">
        <commit-component
          :tag="commitTag"
          :commit-ref="commitRef"
          :commit-url="commitUrl"
          :short-sha="commitShortSha"
          :title="commitTitle"
          :author="commitAuthor"/>
      </div>
    </div>

    <div class="table-section section-wrap section-15 stage-cell">
      <div
        class="table-mobile-header"
        role="rowheader">
        Stages
      </div>
      <div class="table-mobile-content">
        <div class="stage-container dropdown js-mini-pipeline-graph"
          v-if="pipeline.details.stages.length > 0"
          v-for="stage in pipeline.details.stages">
          <pipeline-stage
            :stage="stage"
            :update-dropdown="updateGraphDropdown"
            />
        </div>
      </div>
    </div>

    <pipelines-timeago
      :duration="pipelineDuration"
      :finished-time="pipelineFinishedAt"
      />

    <div
      v-if="displayPipelineActions"
      class="table-section section-20 table-button-footer pipeline-actions">
      <div class="btn-group table-action-buttons">
        <pipelines-actions-component
          v-if="pipeline.details.manual_actions.length"
          :actions="pipeline.details.manual_actions"
          />

        <pipelines-artifacts-component
          v-if="pipeline.details.artifacts.length"
          class="hidden-xs hidden-sm"
          :artifacts="pipeline.details.artifacts"
          />

        <async-button-component
          v-if="pipeline.flags.retryable"
          :endpoint="pipeline.retry_path"
          css-class="js-pipelines-retry-button btn-default btn-retry"
          title="Retry"
          icon="repeat"
          />

        <async-button-component
          v-if="pipeline.flags.cancelable"
          :endpoint="pipeline.cancel_path"
          css-class="js-pipelines-cancel-button btn-remove"
          title="Cancel"
          icon="remove"
          confirm-action-message="Are you sure you want to cancel this pipeline?"
          />
      </div>
    </div>
  </div>
</template>