diff options
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget/components')
13 files changed, 115 insertions, 79 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue index da0a9483f8e..abe5bdd2901 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue @@ -23,6 +23,8 @@ export default { TooltipOnTruncate, FilteredSearchDropdown, ReviewAppLink, + VisualReviewAppLink: () => + import('ee_component/vue_merge_request_widget/components/visual_review_app_link.vue'), }, directives: { GlTooltip: GlTooltipDirective, @@ -37,6 +39,20 @@ export default { type: Boolean, required: true, }, + showVisualReviewApp: { + type: Boolean, + required: false, + default: false, + }, + visualReviewAppMeta: { + type: Object, + required: false, + default: () => ({ + sourceProjectId: '', + mergeRequestId: '', + appUrl: '', + }), + }, }, deployedTextMap: { running: __('Deploying to'), @@ -61,16 +77,16 @@ export default { return this.deployment.external_url; }, hasExternalUrls() { - return !!(this.deployment.external_url && this.deployment.external_url_formatted); + return Boolean(this.deployment.external_url && this.deployment.external_url_formatted); }, hasDeploymentTime() { - return !!(this.deployment.deployed_at && this.deployment.deployed_at_formatted); + return Boolean(this.deployment.deployed_at && this.deployment.deployed_at_formatted); }, hasDeploymentMeta() { - return !!(this.deployment.url && this.deployment.name); + return Boolean(this.deployment.url && this.deployment.name); }, hasMetrics() { - return !!this.deployment.metrics_url; + return Boolean(this.deployment.metrics_url); }, deployedText() { return this.$options.deployedTextMap[this.deployment.status]; @@ -168,6 +184,11 @@ export default { :link="deploymentExternalUrl" :css-class="`deploy-link js-deploy-url inline ${slotProps.className}`" /> + <visual-review-app-link + v-if="showVisualReviewApp" + :link="deploymentExternalUrl" + :app-metadata="visualReviewAppMeta" + /> </template> <template slot="result" slot-scope="slotProps"> @@ -187,11 +208,17 @@ export default { </a> </template> </filtered-search-dropdown> - <review-app-link - v-else - :link="deploymentExternalUrl" - css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inlin" - /> + <template v-else> + <review-app-link + :link="deploymentExternalUrl" + css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inline" + /> + <visual-review-app-link + v-if="showVisualReviewApp" + :link="deploymentExternalUrl" + :app-metadata="visualReviewAppMeta" + /> + </template> </template> <span v-if="deployment.stop_url" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue index 040315b3c66..19a222462b3 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue @@ -37,7 +37,7 @@ export default { </script> <template> - <div class="m-3 ml-5" :class="messageClass"> + <div class="m-3 ml-7" :class="messageClass"> <slot></slot> <gl-link v-if="helpPath" :href="helpPath" target="_blank"> <icon :size="16" name="question-o" class="align-middle" /> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue index 361441640e1..e20a16900d4 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue @@ -128,7 +128,7 @@ export default { :disabled="mr.sourceBranchRemoved" data-target="#modal_merge_info" data-toggle="modal" - class="btn btn-default js-check-out-branch append-right-default" + class="btn btn-default js-check-out-branch append-right-8" type="button" > {{ s__('mrWidget|Check out branch') }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index f5a1ff2f6fd..c377c16fb13 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -5,6 +5,7 @@ import { sprintf, __ } from '~/locale'; import PipelineStage from '~/pipelines/components/stage.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; import Icon from '~/vue_shared/components/icon.vue'; +import PipelineLink from '~/vue_shared/components/ci_pipeline_link.vue'; import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline'; @@ -16,6 +17,7 @@ export default { Icon, TooltipOnTruncate, GlLink, + PipelineLink, LinkedPipelinesMiniList: () => import('ee_component/vue_shared/components/linked_pipelines_mini_list.vue'), }, @@ -94,8 +96,8 @@ export default { </script> <template> - <div v-if="hasPipeline || hasCIError" class="ci-widget media js-ci-widget"> - <template v-if="hasCIError"> + <div class="ci-widget media js-ci-widget"> + <template v-if="!hasPipeline || hasCIError"> <div class="add-border ci-status-icon ci-status-icon-failed ci-error js-ci-error append-right-default" > @@ -112,9 +114,12 @@ export default { <div class="media-body"> <div class="font-weight-bold js-pipeline-info-container"> {{ s__('Pipeline|Pipeline') }} - <gl-link :href="pipeline.path" class="pipeline-id font-weight-normal pipeline-number" - >#{{ pipeline.id }}</gl-link - > + <pipeline-link + :href="pipeline.path" + :pipeline-id="pipeline.id" + :pipeline-iid="pipeline.iid" + class="pipeline-id pipeline-iid font-weight-normal" + /> {{ pipeline.details.status.label }} <template v-if="hasCommitInfo"> {{ s__('Pipeline|for') }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue index 5f5fe67b3c1..03a15ba81ed 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue @@ -30,9 +30,6 @@ export default { }, }, computed: { - pipeline() { - return this.isPostMerge ? this.mr.mergePipeline : this.mr.pipeline; - }, branch() { return this.isPostMerge ? this.mr.targetBranch : this.mr.sourceBranch; }, @@ -48,6 +45,19 @@ export default { hasDeploymentMetrics() { return this.isPostMerge; }, + visualReviewAppMeta() { + return { + appUrl: this.mr.appUrl, + mergeRequestId: this.mr.iid, + sourceProjectId: this.mr.sourceProjectId, + }; + }, + pipeline() { + return this.isPostMerge ? this.mr.mergePipeline : this.mr.pipeline; + }, + showVisualReviewAppLink() { + return Boolean(this.mr.visualReviewFF && this.mr.visualReviewAppAvailable); + }, }, }; </script> @@ -61,14 +71,18 @@ export default { :source-branch-link="branchLink" :troubleshooting-docs-path="mr.troubleshootingDocsPath" /> - <div v-if="deployments.length" slot="footer" class="mr-widget-extension"> - <deployment - v-for="deployment in deployments" - :key="deployment.id" - :class="deploymentClass" - :deployment="deployment" - :show-metrics="hasDeploymentMetrics" - /> - </div> + <template v-slot:footer> + <div v-if="deployments.length" class="mr-widget-extension"> + <deployment + v-for="deployment in deployments" + :key="deployment.id" + :class="deploymentClass" + :deployment="deployment" + :show-metrics="hasDeploymentMetrics" + :show-visual-review-app="true" + :visual-review-app-meta="visualReviewAppMeta" + /> + </div> + </template> </mr-widget-container> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue index de9c122f268..457a71cab95 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue @@ -19,6 +19,6 @@ export default { </script> <template> <a :href="link" target="_blank" rel="noopener noreferrer nofollow" :class="cssClass"> - {{ __('View app') }} <icon name="external-link" /> + {{ __('View app') }} <icon css-classes="fgray" name="external-link" /> </a> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue index 780ecdcdac4..6aad2a26a53 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue @@ -14,7 +14,7 @@ export default { </script> <template> - <p v-once class="mr-info-list mr-links source-branch-removal-status append-bottom-0"> + <p v-once class="mr-info-list mr-links append-bottom-0"> <span class="status-text" v-html="removesBranchText"> </span> <i v-tooltip :title="tooltipTitle" :aria-label="tooltipTitle" class="fa fa-question-circle"> </i> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue index a38f25cce35..acd8037cfb2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue @@ -30,6 +30,7 @@ export default { :id="inputId" :value="value" class="form-control js-gfm-input append-bottom-default commit-message-edit" + dir="auto" required="required" rows="7" @input="$emit('input', $event.target.value)" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue index 1b3af2fccf2..5958c2cf87e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue @@ -1,15 +1,19 @@ <script> +import _ from 'underscore'; +import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge'; import Flash from '../../../flash'; import statusIcon from '../mr_widget_status_icon.vue'; import MrWidgetAuthor from '../../components/mr_widget_author.vue'; import eventHub from '../../event_hub'; +import { AUTO_MERGE_STRATEGIES } from '../../constants'; export default { - name: 'MRWidgetMergeWhenPipelineSucceeds', + name: 'MRWidgetAutoMergeEnabled', components: { MrWidgetAuthor, statusIcon, }, + mixins: [autoMergeMixin], props: { mr: { type: Object, @@ -57,7 +61,7 @@ export default { removeSourceBranch() { const options = { sha: this.mr.sha, - merge_when_pipeline_succeeds: true, + auto_merge_strategy: this.mr.autoMergeStrategy, should_remove_source_branch: true, }; @@ -66,7 +70,7 @@ export default { .merge(options) .then(res => res.data) .then(data => { - if (data.status === 'merge_when_pipeline_succeeds') { + if (_.includes(AUTO_MERGE_STRATEGIES, data.status)) { eventHub.$emit('MRWidgetUpdateRequested'); } }) @@ -84,9 +88,9 @@ export default { <div class="media-body"> <h4 class="d-flex align-items-start"> <span class="append-right-10"> - {{ s__('mrWidget|Set by') }} - <mr-widget-author :author="mr.setToMWPSBy" /> - {{ s__('mrWidget|to be merged automatically when the pipeline succeeds') }} + <span class="js-status-text-before-author">{{ statusTextBeforeAuthor }}</span> + <mr-widget-author :author="mr.setToAutoMergeBy" /> + <span class="js-status-text-after-author">{{ statusTextAfterAuthor }}</span> </span> <a v-if="mr.canCancelAutomaticMerge" @@ -97,7 +101,7 @@ export default { @click.prevent="cancelAutomaticMerge" > <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i> - {{ s__('mrWidget|Cancel automatic merge') }} + {{ cancelButtonText }} </a> </h4> <section class="mr-info-list"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue index a3a44dd8e99..83e7d6db9fa 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue @@ -35,9 +35,7 @@ export default { <status-icon status="warning" /> <div class="media-body space-children"> <span class="bold"> - <template v-if="mr.mergeError" - >{{ mr.mergeError }}.</template - > + <template v-if="mr.mergeError">{{ mr.mergeError }}</template> {{ s__('mrWidget|This merge request failed to be merged automatically') }} </span> <button diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue index f6f445c1cef..3df4a777aca 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue @@ -26,7 +26,7 @@ export default { ); }, showResolveButton() { - return this.mr.conflictResolutionPath && this.mr.canMerge; + return this.mr.conflictResolutionPath && this.mr.canPushToSourceBranch; }, showPopover() { return this.showResolveButton && this.mr.sourceBranchProtected; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index bb76eb1030d..ca1b4a57717 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue @@ -1,8 +1,10 @@ <script> +import _ from 'underscore'; import successSvg from 'icons/_icon_status_success.svg'; import warningSvg from 'icons/_icon_status_warning.svg'; import simplePoll from '~/lib/utils/simple_poll'; import { __ } from '~/locale'; +import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge'; import MergeRequest from '../../../merge_request'; import Flash from '../../../flash'; import statusIcon from '../mr_widget_status_icon.vue'; @@ -11,6 +13,7 @@ import SquashBeforeMerge from './squash_before_merge.vue'; import CommitsHeader from './commits_header.vue'; import CommitEdit from './commit_edit.vue'; import CommitMessageDropdown from './commit_message_dropdown.vue'; +import { AUTO_MERGE_STRATEGIES } from '../../constants'; export default { name: 'ReadyToMerge', @@ -21,6 +24,7 @@ export default { CommitEdit, CommitMessageDropdown, }, + mixins: [readyToMergeMixin], props: { mr: { type: Object, required: true }, service: { type: Object, required: true }, @@ -28,8 +32,6 @@ export default { data() { return { removeSourceBranch: this.mr.shouldRemoveSourceBranch, - mergeWhenBuildSucceeds: false, - setToMergeWhenPipelineSucceeds: false, isMakingRequest: false, isMergingImmediately: false, commitMessage: this.mr.commitMessage, @@ -40,18 +42,18 @@ export default { }; }, computed: { - shouldShowMergeWhenPipelineSucceedsText() { - return this.mr.isPipelineActive; + isAutoMergeAvailable() { + return !_.isEmpty(this.mr.availableAutoMergeStrategies); }, status() { - const { pipeline, isPipelineActive, isPipelineFailed, hasCI, ciStatus } = this.mr; + const { pipeline, isPipelineFailed, hasCI, ciStatus } = this.mr; if (hasCI && !ciStatus) { return 'failed'; + } else if (this.isAutoMergeAvailable) { + return 'pending'; } else if (!pipeline) { return 'success'; - } else if (isPipelineActive) { - return 'pending'; } else if (isPipelineFailed) { return 'failed'; } @@ -85,23 +87,14 @@ export default { mergeButtonText() { if (this.isMergingImmediately) { return __('Merge in progress'); - } else if (this.shouldShowMergeWhenPipelineSucceedsText) { - return __('Merge when pipeline succeeds'); + } else if (this.isAutoMergeAvailable) { + return this.autoMergeText; } - return 'Merge'; + return __('Merge'); }, shouldShowMergeOptionsDropdown() { - return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds; - }, - isMergeButtonDisabled() { - const { commitMessage } = this; - return Boolean( - !commitMessage.length || - !this.shouldShowMergeControls || - this.isMakingRequest || - this.mr.preventMerge, - ); + return this.isAutoMergeAvailable && !this.mr.onlyAllowMergeIfPipelineSucceeds; }, isRemoveSourceBranchButtonDisabled() { return this.isMergeButtonDisabled; @@ -111,7 +104,7 @@ export default { return enableSquashBeforeMerge && commitsCount > 1; }, shouldShowMergeControls() { - return this.mr.isMergeAllowed || this.shouldShowMergeWhenPipelineSucceedsText; + return this.mr.isMergeAllowed || this.isAutoMergeAvailable; }, shouldShowSquashEdit() { return this.squashBeforeMerge && this.shouldShowSquashBeforeMerge; @@ -125,20 +118,15 @@ export default { const { commitMessageWithDescription, commitMessage } = this.mr; this.commitMessage = includeDescription ? commitMessageWithDescription : commitMessage; }, - handleMergeButtonClick(mergeWhenBuildSucceeds, mergeImmediately) { - // TODO: Remove no-param-reassign - if (mergeWhenBuildSucceeds === undefined) { - mergeWhenBuildSucceeds = this.mr.isPipelineActive; // eslint-disable-line no-param-reassign - } else if (mergeImmediately) { + handleMergeButtonClick(useAutoMerge, mergeImmediately = false) { + if (mergeImmediately) { this.isMergingImmediately = true; } - this.setToMergeWhenPipelineSucceeds = mergeWhenBuildSucceeds === true; - const options = { sha: this.mr.sha, commit_message: this.commitMessage, - merge_when_pipeline_succeeds: this.setToMergeWhenPipelineSucceeds, + auto_merge_strategy: useAutoMerge ? this.mr.preferredAutoMergeStrategy : undefined, should_remove_source_branch: this.removeSourceBranch === true, squash: this.squashBeforeMerge, squash_commit_message: this.squashCommitMessage, @@ -151,7 +139,7 @@ export default { .then(data => { const hasError = data.status === 'failed' || data.status === 'hook_validation_error'; - if (data.status === 'merge_when_pipeline_succeeds') { + if (_.includes(AUTO_MERGE_STRATEGIES, data.status)) { eventHub.$emit('MRWidgetUpdateRequested'); } else if (data.status === 'success') { this.initiateMergePolling(); @@ -249,13 +237,13 @@ export default { :class="mergeButtonClass" type="button" class="qa-merge-button" - @click="handleMergeButtonClick()" + @click="handleMergeButtonClick(isAutoMergeAvailable)" > <i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i> {{ mergeButtonText }} </button> <button - v-if="shouldShowMergeOptionsDropdown" + v-if="isAutoMergeAvailable" :disabled="isMergeButtonDisabled" type="button" class="btn btn-sm btn-info dropdown-toggle js-merge-moment" @@ -271,15 +259,13 @@ export default { > <li> <a - class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option" + class="auto_merge_enabled qa-merge-when-pipeline-succeeds-option" href="#" @click.prevent="handleMergeButtonClick(true)" > <span class="media"> <span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span> - <span class="media-body merge-opt-title">{{ - __('Merge when pipeline succeeds') - }}</span> + <span class="media-body merge-opt-title">{{ autoMergeText }}</span> </span> </a> </li> @@ -337,6 +323,7 @@ export default { :commits-count="mr.commitsCount" :target-branch="mr.targetBranch" :is-fast-forward-enabled="mr.ffOnlyEnabled" + :class="{ 'border-bottom': mr.mergeError }" > <ul class="border-top content-list commits-list flex-list"> <commit-edit diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue index b1f5655a15a..accb9d9fef1 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue @@ -29,8 +29,8 @@ export default { </script> <template> - <div class="accept-control inline"> - <label class="merge-param-checkbox"> + <div class="inline"> + <label> <input :checked="value" :disabled="isDisabled" |