diff options
author | Nick Thomas <nick@gitlab.com> | 2019-01-08 15:05:43 +0000 |
---|---|---|
committer | Nick Thomas <nick@gitlab.com> | 2019-01-08 15:05:43 +0000 |
commit | 5a827e0c00066a6b4ce4051108f91c798d07e5bf (patch) | |
tree | 31a16933f9cfbb3afee3763e4313c0341a0aa8be /app | |
parent | 148969947ffd3d2b69c786b9babaed64bba3df9d (diff) | |
parent | aae6d174948a238abf05af2d3038d80b5e8750f4 (diff) | |
download | gitlab-ce-5a827e0c00066a6b4ce4051108f91c798d07e5bf.tar.gz |
Merge branch 'mr-widget-conflicts-protected-branch' into 'master'
Disable resolve conflicts for protected branches
Closes #53463
See merge request gitlab-org/gitlab-ce!23842
Diffstat (limited to 'app')
4 files changed, 74 insertions, 9 deletions
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 27352e0b2b1..f6f445c1cef 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 @@ -1,10 +1,14 @@ <script> -import statusIcon from '../mr_widget_status_icon.vue'; +import $ from 'jquery'; +import _ from 'underscore'; +import { s__, sprintf } from '~/locale'; +import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover'; +import StatusIcon from '../mr_widget_status_icon.vue'; export default { name: 'MRWidgetConflicts', components: { - statusIcon, + StatusIcon, }, props: { /* TODO: This is providing all store and service down when it @@ -15,6 +19,52 @@ export default { default: () => ({}), }, }, + computed: { + popoverTitle() { + return s__( + 'mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected.', + ); + }, + showResolveButton() { + return this.mr.conflictResolutionPath && this.mr.canMerge; + }, + showPopover() { + return this.showResolveButton && this.mr.sourceBranchProtected; + }, + }, + mounted() { + if (this.showPopover) { + const $el = $(this.$refs.popover); + + $el + .popover({ + html: true, + trigger: 'focus', + container: 'body', + placement: 'top', + template: + '<div class="popover" role="tooltip"><div class="arrow"></div><p class="popover-header"></p><div class="popover-body"></div></div>', + title: s__( + 'mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected.', + ), + content: sprintf( + s__('mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}'), + { + link_start: `<a href="${_.escape( + this.mr.conflictsDocsPath, + )}" target="_blank" rel="noopener noreferrer">`, + link_end: '</a>', + }, + false, + ), + }) + .on('mouseenter', mouseenter) + .on('mouseleave', debouncedMouseleave(300)) + .on('show.bs.popover', () => { + window.addEventListener('scroll', togglePopover.bind($el, false), { once: true }); + }); + } + }, }; </script> <template> @@ -38,13 +88,15 @@ To merge this request, first rebase locally.`) }} </span> </span> - <a - v-if="mr.canMerge && mr.conflictResolutionPath" - :href="mr.conflictResolutionPath" - class="js-resolve-conflicts-button btn btn-default btn-sm" - > - {{ s__('mrWidget|Resolve conflicts') }} - </a> + <span v-if="showResolveButton" ref="popover"> + <a + :href="mr.conflictResolutionPath" + :disabled="mr.sourceBranchProtected" + class="js-resolve-conflicts-button btn btn-default btn-sm" + > + {{ s__('mrWidget|Resolve conflicts') }} + </a> + </span> <button v-if="mr.canMerge" class="js-merge-locally-button btn btn-default btn-sm" diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index c777bcca0fa..e5a52c6a7f6 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -29,6 +29,8 @@ export default class MergeRequestStore { this.title = data.title; this.targetBranch = data.target_branch; this.sourceBranch = data.source_branch; + this.sourceBranchProtected = data.source_branch_protected; + this.conflictsDocsPath = data.conflicts_docs_path; this.mergeStatus = data.merge_status; this.commitMessage = data.merge_commit_message; this.shortMergeCommitSha = data.short_merge_commit_sha; diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 1db6c9eff36..44b6ca299ae 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -189,6 +189,10 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated merge_request.subscribed?(current_user, merge_request.target_project) end + def conflicts_docs_path + help_page_path('user/project/merge_requests/resolve_conflicts.md') + end + private def cached_can_be_reverted? diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb index 9731b52f1ad..9361c9f987b 100644 --- a/app/serializers/merge_request_widget_entity.rb +++ b/app/serializers/merge_request_widget_entity.rb @@ -11,6 +11,9 @@ class MergeRequestWidgetEntity < IssuableEntity expose :merge_user_id expose :merge_when_pipeline_succeeds expose :source_branch + expose :source_branch_protected do |merge_request| + merge_request.source_project.present? && ProtectedBranch.protected?(merge_request.source_project, merge_request.source_branch) + end expose :source_project_id expose :source_project_full_path do |merge_request| merge_request.source_project&.full_path @@ -240,6 +243,10 @@ class MergeRequestWidgetEntity < IssuableEntity expose :supports_suggestion?, as: :can_receive_suggestion + expose :conflicts_docs_path do |merge_request| + presenter(merge_request).conflicts_docs_path + end + private delegate :current_user, to: :request |