2018-11-08 19:23:39 +05:30
|
|
|
<script>
|
2018-12-13 13:39:08 +05:30
|
|
|
import _ from 'underscore';
|
|
|
|
import { __ } from '~/locale';
|
2018-03-17 18:26:18 +05:30
|
|
|
import Project from '~/pages/projects/project';
|
|
|
|
import SmartInterval from '~/smart_interval';
|
2019-03-02 22:35:43 +05:30
|
|
|
import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
|
|
|
|
import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
|
|
|
|
import stateMaps from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
|
2018-11-08 19:23:39 +05:30
|
|
|
import createFlash from '../flash';
|
2018-12-13 13:39:08 +05:30
|
|
|
import WidgetHeader from './components/mr_widget_header.vue';
|
|
|
|
import WidgetMergeHelp from './components/mr_widget_merge_help.vue';
|
2019-02-15 15:39:39 +05:30
|
|
|
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
|
2018-12-13 13:39:08 +05:30
|
|
|
import Deployment from './components/deployment.vue';
|
|
|
|
import WidgetRelatedLinks from './components/mr_widget_related_links.vue';
|
|
|
|
import MergedState from './components/states/mr_widget_merged.vue';
|
|
|
|
import ClosedState from './components/states/mr_widget_closed.vue';
|
|
|
|
import MergingState from './components/states/mr_widget_merging.vue';
|
|
|
|
import RebaseState from './components/states/mr_widget_rebase.vue';
|
|
|
|
import WorkInProgressState from './components/states/work_in_progress.vue';
|
|
|
|
import ArchivedState from './components/states/mr_widget_archived.vue';
|
|
|
|
import ConflictsState from './components/states/mr_widget_conflicts.vue';
|
|
|
|
import NothingToMergeState from './components/states/nothing_to_merge.vue';
|
|
|
|
import MissingBranchState from './components/states/mr_widget_missing_branch.vue';
|
|
|
|
import NotAllowedState from './components/states/mr_widget_not_allowed.vue';
|
|
|
|
import ReadyToMergeState from './components/states/ready_to_merge.vue';
|
|
|
|
import ShaMismatchState from './components/states/sha_mismatch.vue';
|
|
|
|
import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
|
|
|
|
import PipelineBlockedState from './components/states/mr_widget_pipeline_blocked.vue';
|
|
|
|
import PipelineFailedState from './components/states/pipeline_failed.vue';
|
|
|
|
import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
|
|
|
|
import MergeWhenPipelineSucceedsState from './components/states/mr_widget_merge_when_pipeline_succeeds.vue';
|
|
|
|
import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
|
|
|
|
import CheckingState from './components/states/mr_widget_checking.vue';
|
|
|
|
import eventHub from './event_hub';
|
|
|
|
import notify from '~/lib/utils/notify';
|
|
|
|
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
|
2018-11-18 11:00:15 +05:30
|
|
|
import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
|
2018-11-08 19:23:39 +05:30
|
|
|
import { setFaviconOverlay } from '../lib/utils/common_utils';
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
export default {
|
|
|
|
el: '#js-vue-mr-widget',
|
|
|
|
name: 'MRWidget',
|
2018-11-08 19:23:39 +05:30
|
|
|
components: {
|
|
|
|
'mr-widget-header': WidgetHeader,
|
|
|
|
'mr-widget-merge-help': WidgetMergeHelp,
|
2019-02-15 15:39:39 +05:30
|
|
|
MrWidgetPipelineContainer,
|
2018-11-08 19:23:39 +05:30
|
|
|
Deployment,
|
|
|
|
'mr-widget-related-links': WidgetRelatedLinks,
|
|
|
|
'mr-widget-merged': MergedState,
|
|
|
|
'mr-widget-closed': ClosedState,
|
|
|
|
'mr-widget-merging': MergingState,
|
|
|
|
'mr-widget-failed-to-merge': FailedToMerge,
|
|
|
|
'mr-widget-wip': WorkInProgressState,
|
|
|
|
'mr-widget-archived': ArchivedState,
|
|
|
|
'mr-widget-conflicts': ConflictsState,
|
|
|
|
'mr-widget-nothing-to-merge': NothingToMergeState,
|
|
|
|
'mr-widget-not-allowed': NotAllowedState,
|
|
|
|
'mr-widget-missing-branch': MissingBranchState,
|
|
|
|
'mr-widget-ready-to-merge': ReadyToMergeState,
|
|
|
|
'sha-mismatch': ShaMismatchState,
|
|
|
|
'mr-widget-checking': CheckingState,
|
|
|
|
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
|
|
|
|
'mr-widget-pipeline-blocked': PipelineBlockedState,
|
|
|
|
'mr-widget-pipeline-failed': PipelineFailedState,
|
|
|
|
'mr-widget-merge-when-pipeline-succeeds': MergeWhenPipelineSucceedsState,
|
|
|
|
'mr-widget-auto-merge-failed': AutoMergeFailed,
|
|
|
|
'mr-widget-rebase': RebaseState,
|
|
|
|
SourceBranchRemovalStatus,
|
2018-11-18 11:00:15 +05:30
|
|
|
GroupedTestReportsApp,
|
2018-11-08 19:23:39 +05:30
|
|
|
},
|
2017-09-10 17:25:29 +05:30
|
|
|
props: {
|
|
|
|
mrData: {
|
|
|
|
type: Object,
|
|
|
|
required: false,
|
2018-11-08 19:23:39 +05:30
|
|
|
default: null,
|
2017-09-10 17:25:29 +05:30
|
|
|
},
|
|
|
|
},
|
2017-08-17 22:00:37 +05:30
|
|
|
data() {
|
2017-09-10 17:25:29 +05:30
|
|
|
const store = new MRWidgetStore(this.mrData || window.gl.mrWidgetData);
|
2017-08-17 22:00:37 +05:30
|
|
|
const service = this.createService(store);
|
|
|
|
return {
|
|
|
|
mr: store,
|
2018-12-13 13:39:08 +05:30
|
|
|
state: store.state,
|
2017-08-17 22:00:37 +05:30
|
|
|
service,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
componentName() {
|
|
|
|
return stateMaps.stateToComponentMap[this.mr.state];
|
|
|
|
},
|
|
|
|
shouldRenderMergeHelp() {
|
|
|
|
return stateMaps.statesToShowHelpWidget.indexOf(this.mr.state) > -1;
|
|
|
|
},
|
|
|
|
shouldRenderPipelines() {
|
2018-03-17 18:26:18 +05:30
|
|
|
return this.mr.hasCI;
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
shouldRenderRelatedLinks() {
|
2018-03-17 18:26:18 +05:30
|
|
|
return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState;
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
2018-05-09 12:01:36 +05:30
|
|
|
shouldRenderSourceBranchRemovalStatus() {
|
2018-12-13 13:39:08 +05:30
|
|
|
return (
|
|
|
|
!this.mr.canRemoveSourceBranch &&
|
|
|
|
this.mr.shouldRemoveSourceBranch &&
|
|
|
|
(!this.mr.isNothingToMergeState && !this.mr.isMergedState)
|
|
|
|
);
|
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
shouldRenderCollaborationStatus() {
|
|
|
|
return this.mr.allowCollaboration && this.mr.isOpen;
|
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
shouldRenderMergedPipeline() {
|
|
|
|
return this.mr.state === 'merged' && !_.isEmpty(this.mr.mergePipeline);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
state(newVal, oldVal) {
|
|
|
|
if (newVal !== oldVal && this.shouldRenderMergedPipeline) {
|
|
|
|
// init polling
|
|
|
|
this.initPostMergeDeploymentsPolling();
|
|
|
|
}
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
},
|
2018-11-08 19:23:39 +05:30
|
|
|
created() {
|
|
|
|
this.initPolling();
|
|
|
|
this.bindEventHubListeners();
|
2018-12-05 23:21:45 +05:30
|
|
|
eventHub.$on('mr.discussion.updated', this.checkStatus);
|
2018-11-08 19:23:39 +05:30
|
|
|
},
|
|
|
|
mounted() {
|
2018-12-13 13:39:08 +05:30
|
|
|
this.setFaviconHelper();
|
|
|
|
this.initDeploymentsPolling();
|
|
|
|
|
|
|
|
if (this.shouldRenderMergedPipeline) {
|
|
|
|
this.initPostMergeDeploymentsPolling();
|
|
|
|
}
|
2018-11-08 19:23:39 +05:30
|
|
|
},
|
2018-12-05 23:21:45 +05:30
|
|
|
beforeDestroy() {
|
|
|
|
eventHub.$off('mr.discussion.updated', this.checkStatus);
|
|
|
|
this.pollingInterval.destroy();
|
|
|
|
this.deploymentsInterval.destroy();
|
2018-12-13 13:39:08 +05:30
|
|
|
|
|
|
|
if (this.postMergeDeploymentsInterval) {
|
|
|
|
this.postMergeDeploymentsInterval.destroy();
|
|
|
|
}
|
2018-12-05 23:21:45 +05:30
|
|
|
},
|
2017-08-17 22:00:37 +05:30
|
|
|
methods: {
|
2019-03-02 22:35:43 +05:30
|
|
|
getServiceEndpoints(store) {
|
|
|
|
return {
|
2017-08-17 22:00:37 +05:30
|
|
|
mergePath: store.mergePath,
|
|
|
|
mergeCheckPath: store.mergeCheckPath,
|
|
|
|
cancelAutoMergePath: store.cancelAutoMergePath,
|
|
|
|
removeWIPPath: store.removeWIPPath,
|
|
|
|
sourceBranchPath: store.sourceBranchPath,
|
|
|
|
ciEnvironmentsStatusPath: store.ciEnvironmentsStatusPath,
|
|
|
|
statusPath: store.statusPath,
|
|
|
|
mergeActionsContentPath: store.mergeActionsContentPath,
|
2018-03-17 18:26:18 +05:30
|
|
|
rebasePath: store.rebasePath,
|
2017-08-17 22:00:37 +05:30
|
|
|
};
|
2019-03-02 22:35:43 +05:30
|
|
|
},
|
|
|
|
createService(store) {
|
|
|
|
return new MRWidgetService(this.getServiceEndpoints(store));
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
checkStatus(cb, isRebased) {
|
2018-12-13 13:39:08 +05:30
|
|
|
return this.service
|
|
|
|
.checkStatus()
|
2018-03-17 18:26:18 +05:30
|
|
|
.then(res => res.data)
|
2018-12-13 13:39:08 +05:30
|
|
|
.then(data => {
|
2018-03-17 18:26:18 +05:30
|
|
|
this.handleNotification(data);
|
2019-02-15 15:39:39 +05:30
|
|
|
this.mr.setData(data, isRebased);
|
2018-03-17 18:26:18 +05:30
|
|
|
this.setFaviconHelper();
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
if (cb) {
|
2018-03-17 18:26:18 +05:30
|
|
|
cb.call(null, data);
|
2017-08-17 22:00:37 +05:30
|
|
|
}
|
|
|
|
})
|
2018-12-13 13:39:08 +05:30
|
|
|
.catch(() => createFlash(__('Something went wrong. Please try again.')));
|
|
|
|
},
|
|
|
|
setFaviconHelper() {
|
|
|
|
if (this.mr.ciStatusFaviconPath) {
|
|
|
|
return setFaviconOverlay(this.mr.ciStatusFaviconPath);
|
|
|
|
}
|
|
|
|
return Promise.resolve();
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
initPolling() {
|
2018-03-17 18:26:18 +05:30
|
|
|
this.pollingInterval = new SmartInterval({
|
2017-08-17 22:00:37 +05:30
|
|
|
callback: this.checkStatus,
|
|
|
|
startingInterval: 10000,
|
|
|
|
maxInterval: 30000,
|
|
|
|
hiddenInterval: 120000,
|
|
|
|
incrementByFactorOf: 5000,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
initDeploymentsPolling() {
|
2018-12-13 13:39:08 +05:30
|
|
|
this.deploymentsInterval = this.deploymentsPoll(this.fetchPreMergeDeployments);
|
|
|
|
},
|
|
|
|
initPostMergeDeploymentsPolling() {
|
|
|
|
this.postMergeDeploymentsInterval = this.deploymentsPoll(this.fetchPostMergeDeployments);
|
|
|
|
},
|
|
|
|
deploymentsPoll(callback) {
|
|
|
|
return new SmartInterval({
|
|
|
|
callback,
|
2017-08-17 22:00:37 +05:30
|
|
|
startingInterval: 30000,
|
|
|
|
maxInterval: 120000,
|
|
|
|
hiddenInterval: 240000,
|
|
|
|
incrementByFactorOf: 15000,
|
|
|
|
immediateExecution: true,
|
|
|
|
});
|
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
fetchDeployments(target) {
|
|
|
|
return this.service.fetchDeployments(target);
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
fetchPreMergeDeployments() {
|
|
|
|
return this.fetchDeployments()
|
|
|
|
.then(({ data }) => {
|
2018-03-17 18:26:18 +05:30
|
|
|
if (data.length) {
|
|
|
|
this.mr.deployments = data;
|
2017-08-17 22:00:37 +05:30
|
|
|
}
|
|
|
|
})
|
2018-12-13 13:39:08 +05:30
|
|
|
.catch(() => this.throwDeploymentsError());
|
|
|
|
},
|
|
|
|
fetchPostMergeDeployments() {
|
|
|
|
return this.fetchDeployments('merge_commit')
|
|
|
|
.then(({ data }) => {
|
|
|
|
if (data.length) {
|
|
|
|
this.mr.postMergeDeployments = data;
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(() => this.throwDeploymentsError());
|
|
|
|
},
|
|
|
|
throwDeploymentsError() {
|
|
|
|
createFlash(
|
|
|
|
__(
|
|
|
|
'Something went wrong while fetching the environments for this merge request. Please try again.',
|
|
|
|
),
|
|
|
|
);
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
fetchActionsContent() {
|
2018-12-13 13:39:08 +05:30
|
|
|
this.service
|
|
|
|
.fetchMergeActionsContent()
|
|
|
|
.then(res => {
|
2018-03-17 18:26:18 +05:30
|
|
|
if (res.data) {
|
2017-08-17 22:00:37 +05:30
|
|
|
const el = document.createElement('div');
|
2018-03-17 18:26:18 +05:30
|
|
|
el.innerHTML = res.data;
|
2017-08-17 22:00:37 +05:30
|
|
|
document.body.appendChild(el);
|
2018-03-17 18:26:18 +05:30
|
|
|
Project.initRefSwitcher();
|
2017-08-17 22:00:37 +05:30
|
|
|
}
|
|
|
|
})
|
2018-12-13 13:39:08 +05:30
|
|
|
.catch(() => createFlash(__('Something went wrong. Please try again.')));
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
handleNotification(data) {
|
|
|
|
if (data.ci_status === this.mr.ciStatus) return;
|
2018-03-17 18:26:18 +05:30
|
|
|
if (!data.pipeline) return;
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
const { label } = data.pipeline.details.status;
|
2017-08-17 22:00:37 +05:30
|
|
|
const title = `Pipeline ${label}`;
|
|
|
|
const message = `Pipeline ${label} for "${data.title}"`;
|
|
|
|
|
|
|
|
notify.notifyMe(title, message, this.mr.gitlabLogo);
|
|
|
|
},
|
|
|
|
resumePolling() {
|
|
|
|
this.pollingInterval.resume();
|
|
|
|
},
|
|
|
|
stopPolling() {
|
|
|
|
this.pollingInterval.stopTimer();
|
|
|
|
},
|
|
|
|
bindEventHubListeners() {
|
2018-12-13 13:39:08 +05:30
|
|
|
eventHub.$on('MRWidgetUpdateRequested', cb => {
|
2017-08-17 22:00:37 +05:30
|
|
|
this.checkStatus(cb);
|
|
|
|
});
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
eventHub.$on('MRWidgetRebaseSuccess', cb => {
|
|
|
|
this.checkStatus(cb, true);
|
|
|
|
});
|
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
// `params` should be an Array contains a Boolean, like `[true]`
|
|
|
|
// Passing parameter as Boolean didn't work.
|
2018-12-13 13:39:08 +05:30
|
|
|
eventHub.$on('SetBranchRemoveFlag', params => {
|
2018-11-08 19:23:39 +05:30
|
|
|
[this.mr.isRemovingSourceBranch] = params;
|
2017-08-17 22:00:37 +05:30
|
|
|
});
|
|
|
|
|
2018-12-13 13:39:08 +05:30
|
|
|
eventHub.$on('FailedToMerge', mergeError => {
|
2017-08-17 22:00:37 +05:30
|
|
|
this.mr.state = 'failedToMerge';
|
|
|
|
this.mr.mergeError = mergeError;
|
|
|
|
});
|
|
|
|
|
2018-12-13 13:39:08 +05:30
|
|
|
eventHub.$on('UpdateWidgetData', data => {
|
2017-08-17 22:00:37 +05:30
|
|
|
this.mr.setData(data);
|
|
|
|
});
|
|
|
|
|
|
|
|
eventHub.$on('FetchActionsContent', () => {
|
|
|
|
this.fetchActionsContent();
|
|
|
|
});
|
|
|
|
|
|
|
|
eventHub.$on('EnablePolling', () => {
|
|
|
|
this.resumePolling();
|
|
|
|
});
|
|
|
|
|
|
|
|
eventHub.$on('DisablePolling', () => {
|
|
|
|
this.stopPolling();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2018-11-08 19:23:39 +05:30
|
|
|
};
|
|
|
|
</script>
|
|
|
|
<template>
|
|
|
|
<div class="mr-state-widget prepend-top-default">
|
2019-02-15 15:39:39 +05:30
|
|
|
<mr-widget-header :mr="mr" />
|
|
|
|
<mr-widget-pipeline-container
|
2019-01-03 12:48:30 +05:30
|
|
|
v-if="shouldRenderPipelines"
|
2019-02-15 15:39:39 +05:30
|
|
|
class="mr-widget-workflow"
|
|
|
|
:mr="mr"
|
2019-01-03 12:48:30 +05:30
|
|
|
/>
|
2019-02-15 15:39:39 +05:30
|
|
|
<div class="mr-section-container mr-widget-workflow">
|
2018-11-18 11:00:15 +05:30
|
|
|
<grouped-test-reports-app
|
|
|
|
v-if="mr.testResultsPath"
|
2018-12-13 13:39:08 +05:30
|
|
|
class="js-reports-container"
|
2018-11-18 11:00:15 +05:30
|
|
|
:endpoint="mr.testResultsPath"
|
|
|
|
/>
|
2018-12-13 13:39:08 +05:30
|
|
|
|
2019-03-13 22:55:13 +05:30
|
|
|
<div class="mr-widget-section">
|
2019-02-15 15:39:39 +05:30
|
|
|
<component :is="componentName" :mr="mr" :service="service" />
|
2018-11-08 19:23:39 +05:30
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
<section v-if="shouldRenderCollaborationStatus" class="mr-info-list mr-links">
|
|
|
|
{{ s__('mrWidget|Allows commits from members who can merge to the target branch') }}
|
2018-11-08 19:23:39 +05:30
|
|
|
</section>
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
<mr-widget-related-links
|
|
|
|
v-if="shouldRenderRelatedLinks"
|
|
|
|
:state="mr.state"
|
2018-11-08 19:23:39 +05:30
|
|
|
:related-links="mr.relatedLinks"
|
|
|
|
/>
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
|
2017-09-10 17:25:29 +05:30
|
|
|
</div>
|
2019-02-15 15:39:39 +05:30
|
|
|
<div v-if="shouldRenderMergeHelp" class="mr-widget-footer"><mr-widget-merge-help /></div>
|
2017-08-17 22:00:37 +05:30
|
|
|
</div>
|
2019-02-15 15:39:39 +05:30
|
|
|
<mr-widget-pipeline-container
|
|
|
|
v-if="shouldRenderMergedPipeline"
|
|
|
|
class="js-post-merge-pipeline mr-widget-workflow"
|
|
|
|
:mr="mr"
|
|
|
|
:is-post-merge="true"
|
|
|
|
/>
|
2018-11-08 19:23:39 +05:30
|
|
|
</div>
|
|
|
|
</template>
|