diff options
Diffstat (limited to 'app/assets/javascripts/projects/commit_box/info')
9 files changed, 221 insertions, 3 deletions
diff --git a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue index da14b1e8470..8511f9bdb0f 100644 --- a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue +++ b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_mini_graph.vue @@ -3,11 +3,20 @@ import { GlLoadingIcon } from '@gitlab/ui'; import createFlash from '~/flash'; import { __ } from '~/locale'; import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mini_graph.vue'; +import { + getQueryHeaders, + toggleQueryPollingByVisibility, +} from '~/pipelines/components/graph/utils'; +import { formatStages } from '../utils'; import getLinkedPipelinesQuery from '../graphql/queries/get_linked_pipelines.query.graphql'; +import getPipelineStagesQuery from '../graphql/queries/get_pipeline_stages.query.graphql'; +import { COMMIT_BOX_POLL_INTERVAL } from '../constants'; export default { i18n: { linkedPipelinesFetchError: __('There was a problem fetching linked pipelines.'), + stageConversionError: __('There was a problem handling the pipeline data.'), + stagesFetchError: __('There was a problem fetching the pipeline stages.'), }, components: { GlLoadingIcon, @@ -22,6 +31,9 @@ export default { iid: { default: '', }, + graphqlResourceEtag: { + default: '', + }, }, props: { stages: { @@ -48,10 +60,31 @@ export default { createFlash({ message: this.$options.i18n.linkedPipelinesFetchError }); }, }, + pipelineStages: { + context() { + return getQueryHeaders(this.graphqlResourceEtag); + }, + query: getPipelineStagesQuery, + pollInterval: COMMIT_BOX_POLL_INTERVAL, + variables() { + return { + fullPath: this.fullPath, + iid: this.iid, + }; + }, + update({ project }) { + return project?.pipeline?.stages?.nodes || []; + }, + error() { + createFlash({ message: this.$options.i18n.stagesFetchError }); + }, + }, }, data() { return { + formattedStages: [], pipeline: null, + pipelineStages: [], }; }, computed: { @@ -65,6 +98,25 @@ export default { return this.pipeline?.upstream; }, }, + watch: { + pipelineStages() { + // pipelineStages are from GraphQL + // stages are from REST + // we do this to use dropdown_path for fetching jobs on stage click + try { + this.formattedStages = formatStages(this.pipelineStages, this.stages); + } catch (error) { + createFlash({ + message: this.$options.i18n.stageConversionError, + captureError: true, + error, + }); + } + }, + }, + mounted() { + toggleQueryPollingByVisibility(this.$apollo.queries.pipelineStages); + }, }; </script> @@ -79,7 +131,7 @@ export default { /> <pipeline-mini-graph - :stages="stages" + :stages="formattedStages" class="gl-display-inline" data-testid="commit-box-mini-graph" /> diff --git a/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue new file mode 100644 index 00000000000..5a9d3129809 --- /dev/null +++ b/app/assets/javascripts/projects/commit_box/info/components/commit_box_pipeline_status.vue @@ -0,0 +1,74 @@ +<script> +import { GlLoadingIcon, GlLink } from '@gitlab/ui'; +import CiIcon from '~/vue_shared/components/ci_icon.vue'; +import createFlash from '~/flash'; +import { + getQueryHeaders, + toggleQueryPollingByVisibility, +} from '~/pipelines/components/graph/utils'; +import getLatestPipelineStatusQuery from '../graphql/queries/get_latest_pipeline_status.query.graphql'; +import { COMMIT_BOX_POLL_INTERVAL, PIPELINE_STATUS_FETCH_ERROR } from '../constants'; + +export default { + PIPELINE_STATUS_FETCH_ERROR, + components: { + CiIcon, + GlLoadingIcon, + GlLink, + }, + inject: { + fullPath: { + default: '', + }, + iid: { + default: '', + }, + graphqlResourceEtag: { + default: '', + }, + }, + apollo: { + pipelineStatus: { + context() { + return getQueryHeaders(this.graphqlResourceEtag); + }, + query: getLatestPipelineStatusQuery, + pollInterval: COMMIT_BOX_POLL_INTERVAL, + variables() { + return { + fullPath: this.fullPath, + iid: this.iid, + }; + }, + update({ project }) { + return project?.pipeline?.detailedStatus || {}; + }, + error() { + createFlash({ message: this.$options.PIPELINE_STATUS_FETCH_ERROR }); + }, + }, + }, + data() { + return { + pipelineStatus: {}, + }; + }, + computed: { + loading() { + return this.$apollo.queries.pipelineStatus.loading; + }, + }, + mounted() { + toggleQueryPollingByVisibility(this.$apollo.queries.pipelineStatus); + }, +}; +</script> + +<template> + <div class="gl-display-inline-block gl-vertical-align-middle gl-mr-2"> + <gl-loading-icon v-if="loading" /> + <gl-link v-else :href="pipelineStatus.detailsPath"> + <ci-icon :status="pipelineStatus" :size="24" /> + </gl-link> + </div> +</template> diff --git a/app/assets/javascripts/projects/commit_box/info/constants.js b/app/assets/javascripts/projects/commit_box/info/constants.js new file mode 100644 index 00000000000..be0bf715314 --- /dev/null +++ b/app/assets/javascripts/projects/commit_box/info/constants.js @@ -0,0 +1,7 @@ +import { __ } from '~/locale'; + +export const COMMIT_BOX_POLL_INTERVAL = 10000; + +export const PIPELINE_STATUS_FETCH_ERROR = __( + 'There was a problem fetching the latest pipeline status.', +); diff --git a/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_latest_pipeline_status.query.graphql b/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_latest_pipeline_status.query.graphql new file mode 100644 index 00000000000..cec96f82336 --- /dev/null +++ b/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_latest_pipeline_status.query.graphql @@ -0,0 +1,14 @@ +query getLatestPipelineStatus($fullPath: ID!, $iid: ID!) { + project(fullPath: $fullPath) { + id + pipeline(iid: $iid) { + id + detailedStatus { + id + detailsPath + icon + group + } + } + } +} diff --git a/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_pipeline_stages.query.graphql b/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_pipeline_stages.query.graphql new file mode 100644 index 00000000000..69a29947b16 --- /dev/null +++ b/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_pipeline_stages.query.graphql @@ -0,0 +1,19 @@ +query getPipelineStages($fullPath: ID!, $iid: ID!) { + project(fullPath: $fullPath) { + id + pipeline(iid: $iid) { + id + stages { + nodes { + id + name + detailedStatus { + id + icon + group + } + } + } + } + } +} diff --git a/app/assets/javascripts/projects/commit_box/info/index.js b/app/assets/javascripts/projects/commit_box/info/index.js index 69fe2d30489..7500c152b6a 100644 --- a/app/assets/javascripts/projects/commit_box/info/index.js +++ b/app/assets/javascripts/projects/commit_box/info/index.js @@ -2,6 +2,7 @@ import { fetchCommitMergeRequests } from '~/commit_merge_requests'; import { initCommitPipelineMiniGraph } from './init_commit_pipeline_mini_graph'; import { initDetailsButton } from './init_details_button'; import { loadBranches } from './load_branches'; +import initCommitPipelineStatus from './init_commit_pipeline_status'; export const initCommitBoxInfo = () => { // Display commit related branches @@ -14,4 +15,6 @@ export const initCommitBoxInfo = () => { initCommitPipelineMiniGraph(); initDetailsButton(); + + initCommitPipelineStatus(); }; diff --git a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js index 1d4ec4c110b..c206e648561 100644 --- a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js +++ b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js @@ -5,7 +5,7 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient(), + defaultClient: createDefaultClient({}, { useGet: true }), }); export const initCommitPipelineMiniGraph = async (selector = '.js-commit-pipeline-mini-graph') => { @@ -15,7 +15,7 @@ export const initCommitPipelineMiniGraph = async (selector = '.js-commit-pipelin return; } - const { stages, fullPath, iid } = el.dataset; + const { stages, fullPath, iid, graphqlResourceEtag } = el.dataset; // Some commits have no pipeline, code splitting to load the pipeline optionally const { default: CommitBoxPipelineMiniGraph } = await import( @@ -30,6 +30,7 @@ export const initCommitPipelineMiniGraph = async (selector = '.js-commit-pipelin fullPath, iid, dataMethod: 'graphql', + graphqlResourceEtag, }, render(createElement) { return createElement(CommitBoxPipelineMiniGraph, { diff --git a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_status.js b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_status.js new file mode 100644 index 00000000000..d5e62531283 --- /dev/null +++ b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_status.js @@ -0,0 +1,34 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import CommitBoxPipelineStatus from './components/commit_box_pipeline_status.vue'; + +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient({}, { useGet: true }), +}); + +export default (selector = '.js-commit-pipeline-status') => { + const el = document.querySelector(selector); + + if (!el) { + return; + } + + const { fullPath, iid, graphqlResourceEtag } = el.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el, + apolloProvider, + provide: { + fullPath, + iid, + graphqlResourceEtag, + }, + render(createElement) { + return createElement(CommitBoxPipelineStatus); + }, + }); +}; diff --git a/app/assets/javascripts/projects/commit_box/info/utils.js b/app/assets/javascripts/projects/commit_box/info/utils.js new file mode 100644 index 00000000000..ea7eb35cbaf --- /dev/null +++ b/app/assets/javascripts/projects/commit_box/info/utils.js @@ -0,0 +1,14 @@ +export const formatStages = (graphQLStages = [], restStages = []) => { + if (graphQLStages.length !== restStages.length) { + throw new Error('Rest stages and graphQl stages must be the same length'); + } + + return graphQLStages.map((stage, index) => { + return { + name: stage.name, + status: stage.detailedStatus, + dropdown_path: restStages[index]?.dropdown_path || '', + title: restStages[index].title || '', + }; + }); +}; |