Commit c49872e1 authored by Phil Hughes's avatar Phil Hughes

Fixed merge blocked states styling

Fixes the styling of all the merge blocked state components
to match the new design specs.

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/343782
parent 05b048ca
<script> <script>
import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ciIcon from '../../vue_shared/components/ci_icon.vue'; import ciIcon from '../../vue_shared/components/ci_icon.vue';
export default { export default {
...@@ -8,6 +9,7 @@ export default { ...@@ -8,6 +9,7 @@ export default {
GlButton, GlButton,
GlLoadingIcon, GlLoadingIcon,
}, },
mixins: [glFeatureFlagMixin()],
props: { props: {
status: { status: {
type: String, type: String,
...@@ -42,7 +44,7 @@ export default { ...@@ -42,7 +44,7 @@ export default {
</div> </div>
<gl-button <gl-button
v-if="showDisabledButton" v-if="!glFeatures.restructuredMrWidget && showDisabledButton"
category="primary" category="primary"
variant="success" variant="success"
data-testid="disabled-merge-button" data-testid="disabled-merge-button"
......
<script> <script>
import { GlButton } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import notesEventHub from '~/notes/event_hub';
import StatusIcon from '../mr_widget_status_icon.vue'; import StatusIcon from '../mr_widget_status_icon.vue';
export default { export default {
i18n: { i18n: {
pipelineFailed: s__(
'mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure.',
),
approvalNeeded: s__('mrWidget|Merge blocked: this merge request must be approved.'), approvalNeeded: s__('mrWidget|Merge blocked: this merge request must be approved.'),
unresolvedDiscussions: s__('mrWidget|Merge blocked: all threads must be resolved.'), blockingMergeRequests: s__(
'mrWidget|Merge blocked: you can only merge once above items are resolved.',
),
}, },
components: { components: {
StatusIcon, StatusIcon,
GlButton,
}, },
props: { props: {
mr: { mr: {
...@@ -24,22 +20,15 @@ export default { ...@@ -24,22 +20,15 @@ export default {
}, },
computed: { computed: {
failedText() { failedText() {
if (this.mr.isPipelineFailed) { if (this.mr.approvals && !this.mr.isApproved) {
return this.$options.i18n.pipelineFailed;
} else if (this.mr.approvals && !this.mr.isApproved) {
return this.$options.i18n.approvalNeeded; return this.$options.i18n.approvalNeeded;
} else if (this.mr.hasMergeableDiscussionsState) { } else if (this.mr.blockingMergeRequests?.total_count > 0) {
return this.$options.i18n.unresolvedDiscussions; return this.$options.i18n.blockingMergeRequests;
} }
return null; return null;
}, },
}, },
methods: {
jumpToFirstUnresolvedDiscussion() {
notesEventHub.$emit('jumpToFirstUnresolvedDiscussion');
},
},
}; };
</script> </script>
...@@ -48,28 +37,6 @@ export default { ...@@ -48,28 +37,6 @@ export default {
<status-icon status="warning" /> <status-icon status="warning" />
<p class="media-body gl-m-0! gl-font-weight-bold gl-text-black-normal!"> <p class="media-body gl-m-0! gl-font-weight-bold gl-text-black-normal!">
{{ failedText }} {{ failedText }}
<template v-if="failedText == $options.i18n.unresolvedDiscussions">
<gl-button
class="gl-ml-3"
size="small"
variant="confirm"
data-testid="jumpToUnresolved"
@click="jumpToFirstUnresolvedDiscussion"
>
{{ s__('mrWidget|Jump to first unresolved thread') }}
</gl-button>
<gl-button
v-if="mr.createIssueToResolveDiscussionsPath"
:href="mr.createIssueToResolveDiscussionsPath"
class="gl-ml-3"
size="small"
variant="confirm"
category="secondary"
data-testid="resolveIssue"
>
{{ s__('mrWidget|Create issue to resolve all threads') }}
</gl-button>
</template>
</p> </p>
</div> </div>
</template> </template>
<script> <script>
import { GlButton } from '@gitlab/ui'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetArchived', name: 'MRWidgetArchived',
components: { components: {
GlButton,
statusIcon, statusIcon,
}, },
mixins: [glFeatureFlagMixin()],
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<div class="space-children"> <div class="space-children">
<status-icon status="warning" /> <status-icon status="warning" show-disabled-button />
<gl-button category="secondary" variant="success" :disabled="true">
{{ s__('mrWidget|Merge') }}
</gl-button>
</div> </div>
<div class="media-body"> <div class="media-body">
<span class="bold"> <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
{{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }} {{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }}
</span> </span>
</div> </div>
......
...@@ -12,9 +12,11 @@ export default { ...@@ -12,9 +12,11 @@ export default {
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon :show-disabled-button="!glFeatures.restructuredMrWidget" status="loading" /> <status-icon :show-disabled-button="true" status="loading" />
<div class="media-body space-children"> <div class="media-body space-children">
<span class="bold"> {{ s__('mrWidget|Checking if merge request can be merged…') }} </span> <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
{{ s__('mrWidget|Checking if merge request can be merged…') }}
</span>
</div> </div>
</div> </div>
</template> </template>
...@@ -109,14 +109,18 @@ export default { ...@@ -109,14 +109,18 @@ export default {
</gl-skeleton-loader> </gl-skeleton-loader>
</div> </div>
<div v-else class="media-body space-children gl-display-flex gl-align-items-center"> <div v-else class="media-body space-children gl-display-flex gl-align-items-center">
<span v-if="shouldBeRebased" class="bold"> <span
v-if="shouldBeRebased"
:class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
class="bold"
>
{{ {{
s__(`mrWidget|Merge blocked: fast-forward merge is not possible. s__(`mrWidget|Merge blocked: fast-forward merge is not possible.
To merge this request, first rebase locally.`) To merge this request, first rebase locally.`)
}} }}
</span> </span>
<template v-else> <template v-else>
<span class="bold"> <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
{{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }} {{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }}
<span v-if="!canMerge"> <span v-if="!canMerge">
{{ {{
...@@ -129,6 +133,7 @@ export default { ...@@ -129,6 +133,7 @@ export default {
<gl-button <gl-button
v-if="showResolveButton" v-if="showResolveButton"
:href="mr.conflictResolutionPath" :href="mr.conflictResolutionPath"
:size="glFeatures.restructuredMrWidget ? 'small' : 'medium'"
data-testid="resolve-conflicts-button" data-testid="resolve-conflicts-button"
> >
{{ s__('mrWidget|Resolve conflicts') }} {{ s__('mrWidget|Resolve conflicts') }}
...@@ -136,6 +141,7 @@ export default { ...@@ -136,6 +141,7 @@ export default {
<gl-button <gl-button
v-if="canMerge" v-if="canMerge"
v-gl-modal-directive="'modal-merge-info'" v-gl-modal-directive="'modal-merge-info'"
:size="glFeatures.restructuredMrWidget ? 'small' : 'medium'"
data-testid="merge-locally-button" data-testid="merge-locally-button"
> >
{{ s__('mrWidget|Merge locally') }} {{ s__('mrWidget|Merge locally') }}
......
...@@ -74,10 +74,21 @@ export default { ...@@ -74,10 +74,21 @@ export default {
<status-icon :show-disabled-button="true" status="warning" /> <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children"> <div class="media-body space-children">
<span class="bold js-branch-text"> <span
:class="{
'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
}"
class="bold js-branch-text"
>
<span class="capitalize" data-testid="missingBranchName"> {{ missingBranchName }} </span> <span class="capitalize" data-testid="missingBranchName"> {{ missingBranchName }} </span>
{{ s__('mrWidget|branch does not exist.') }} {{ missingBranchNameMessage }} {{ s__('mrWidget|branch does not exist.') }} {{ missingBranchNameMessage }}
<gl-icon v-gl-tooltip :title="message" :aria-label="message" name="question-o" /> <gl-icon
v-gl-tooltip
:title="message"
:aria-label="message"
name="question-o"
class="gl-text-blue-600 gl-cursor-pointer"
/>
</span> </span>
</div> </div>
</div> </div>
......
<script> <script>
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import StatusIcon from '../mr_widget_status_icon.vue'; import StatusIcon from '../mr_widget_status_icon.vue';
export default { export default {
...@@ -6,13 +7,14 @@ export default { ...@@ -6,13 +7,14 @@ export default {
components: { components: {
StatusIcon, StatusIcon,
}, },
mixins: [glFeatureFlagMixin()],
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" /> <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children"> <div class="media-body space-children">
<span class="bold"> <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
{{ {{
s__( s__(
`mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`, `mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`,
......
...@@ -152,12 +152,14 @@ export default { ...@@ -152,12 +152,14 @@ export default {
<div class="rebase-state-find-class-convention media media-body space-children"> <div class="rebase-state-find-class-convention media media-body space-children">
<span <span
v-if="rebaseInProgress || isMakingRequest" v-if="rebaseInProgress || isMakingRequest"
:class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
class="gl-font-weight-bold" class="gl-font-weight-bold"
data-testid="rebase-message" data-testid="rebase-message"
>{{ __('Rebase in progress') }}</span >{{ __('Rebase in progress') }}</span
> >
<span <span
v-if="!rebaseInProgress && !canPushToSourceBranch" v-if="!rebaseInProgress && !canPushToSourceBranch"
:class="{ 'gl-text-body!': glFeatures.restructuredMrWidget }"
class="gl-font-weight-bold gl-ml-0!" class="gl-font-weight-bold gl-ml-0!"
data-testid="rebase-message" data-testid="rebase-message"
>{{ fastForwardMergeText }}</span >{{ fastForwardMergeText }}</span
...@@ -167,6 +169,7 @@ export default { ...@@ -167,6 +169,7 @@ export default {
class="accept-merge-holder clearfix js-toggle-container accept-action media space-children" class="accept-merge-holder clearfix js-toggle-container accept-action media space-children"
> >
<gl-button <gl-button
v-if="!glFeatures.restructuredMrWidget"
:loading="isMakingRequest" :loading="isMakingRequest"
variant="confirm" variant="confirm"
data-qa-selector="mr_rebase_button" data-qa-selector="mr_rebase_button"
...@@ -176,6 +179,7 @@ export default { ...@@ -176,6 +179,7 @@ export default {
</gl-button> </gl-button>
<span <span
v-if="!rebasingError" v-if="!rebasingError"
:class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
class="gl-font-weight-bold" class="gl-font-weight-bold"
data-testid="rebase-message" data-testid="rebase-message"
data-qa-selector="no_fast_forward_message_content" data-qa-selector="no_fast_forward_message_content"
...@@ -186,6 +190,17 @@ export default { ...@@ -186,6 +190,17 @@ export default {
<span v-else class="gl-font-weight-bold danger" data-testid="rebase-message">{{ <span v-else class="gl-font-weight-bold danger" data-testid="rebase-message">{{
rebasingError rebasingError
}}</span> }}</span>
<gl-button
v-if="glFeatures.restructuredMrWidget"
:loading="isMakingRequest"
variant="confirm"
size="small"
data-qa-selector="mr_rebase_button"
class="gl-ml-3!"
@click="rebase"
>
{{ __('Rebase') }}
</gl-button>
</div> </div>
</div> </div>
</template> </template>
......
<script> <script>
import { GlLink, GlSprintf } from '@gitlab/ui'; import { GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper'; import { helpPagePath } from '~/helpers/help_page_helper';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
...@@ -11,6 +12,7 @@ export default { ...@@ -11,6 +12,7 @@ export default {
GlSprintf, GlSprintf,
statusIcon, statusIcon,
}, },
mixins: [glFeatureFlagMixin()],
computed: { computed: {
troubleshootingDocsPath() { troubleshootingDocsPath() {
return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' }); return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' });
...@@ -28,7 +30,7 @@ export default { ...@@ -28,7 +30,7 @@ export default {
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" /> <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children"> <div class="media-body space-children">
<span class="bold"> <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
<gl-sprintf :message="$options.i18n.failedMessage"> <gl-sprintf :message="$options.i18n.failedMessage">
<template #link="{ content }"> <template #link="{ content }">
<gl-link :href="troubleshootingDocsPath" target="_blank"> <gl-link :href="troubleshootingDocsPath" target="_blank">
......
...@@ -529,7 +529,7 @@ export default { ...@@ -529,7 +529,7 @@ export default {
<template> <template>
<div <div
:class="{ :class="{
'gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7': 'gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7 gl-rounded-bottom-left-base gl-rounded-bottom-right-base':
glFeatures.restructuredMrWidget, glFeatures.restructuredMrWidget,
}" }"
> >
......
<script> <script>
import { GlButton } from '@gitlab/ui'; import { GlButton } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { I18N_SHA_MISMATCH } from '../../i18n'; import { I18N_SHA_MISMATCH } from '../../i18n';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
...@@ -12,6 +13,7 @@ export default { ...@@ -12,6 +13,7 @@ export default {
i18n: { i18n: {
I18N_SHA_MISMATCH, I18N_SHA_MISMATCH,
}, },
mixins: [glFeatureFlagMixin()],
props: { props: {
mr: { mr: {
type: Object, type: Object,
...@@ -25,7 +27,11 @@ export default { ...@@ -25,7 +27,11 @@ export default {
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon :show-disabled-button="false" status="warning" /> <status-icon :show-disabled-button="false" status="warning" />
<div class="media-body"> <div class="media-body">
<span class="gl-font-weight-bold" data-qa-selector="head_mismatch_content"> <span
:class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
class="gl-font-weight-bold"
data-qa-selector="head_mismatch_content"
>
{{ $options.i18n.I18N_SHA_MISMATCH.warningMessage }} {{ $options.i18n.I18N_SHA_MISMATCH.warningMessage }}
</span> </span>
<gl-button <gl-button
......
<script> <script>
import { GlButton } from '@gitlab/ui'; import { GlButton } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import notesEventHub from '~/notes/event_hub'; import notesEventHub from '~/notes/event_hub';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
...@@ -9,6 +10,7 @@ export default { ...@@ -9,6 +10,7 @@ export default {
statusIcon, statusIcon,
GlButton, GlButton,
}, },
mixins: [glFeatureFlagMixin()],
props: { props: {
mr: { mr: {
type: Object, type: Object,
...@@ -25,16 +27,24 @@ export default { ...@@ -25,16 +27,24 @@ export default {
<template> <template>
<div class="mr-widget-body media gl-flex-wrap"> <div class="mr-widget-body media gl-flex-wrap">
<status-icon :show-disabled-button="true" status="warning" /> <status-icon show-disabled-button status="warning" />
<div class="media-body"> <div class="media-body">
<span class="gl-ml-3 gl-font-weight-bold gl-display-block gl-w-100">{{ <span
s__('mrWidget|Merge blocked: all threads must be resolved.') :class="{
}}</span> 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
'gl-display-block': !glFeatures.restructuredMrWidget,
}"
class="gl-ml-3 gl-font-weight-bold gl-w-100"
>
{{ s__('mrWidget|Merge blocked: all threads must be resolved.') }}
</span>
<gl-button <gl-button
data-testid="jump-to-first" data-testid="jump-to-first"
class="gl-ml-3" class="gl-ml-3"
size="small" size="small"
icon="comment-next" :icon="glFeatures.restructuredMrWidget ? undefined : 'comment-next'"
:variant="glFeatures.restructuredMrWidget && 'confirm'"
:category="glFeatures.restructuredMrWidget && 'secondary'"
@click="jumpToFirstUnresolvedDiscussion" @click="jumpToFirstUnresolvedDiscussion"
> >
{{ s__('mrWidget|Jump to first unresolved thread') }} {{ s__('mrWidget|Jump to first unresolved thread') }}
...@@ -44,7 +54,7 @@ export default { ...@@ -44,7 +54,7 @@ export default {
:href="mr.createIssueToResolveDiscussionsPath" :href="mr.createIssueToResolveDiscussionsPath"
class="js-create-issue gl-ml-3" class="js-create-issue gl-ml-3"
size="small" size="small"
icon="issue-new" :icon="glFeatures.restructuredMrWidget ? undefined : 'issue-new'"
> >
{{ s__('mrWidget|Create issue to resolve all threads') }} {{ s__('mrWidget|Create issue to resolve all threads') }}
</gl-button> </gl-button>
......
...@@ -166,7 +166,10 @@ export default { ...@@ -166,7 +166,10 @@ export default {
<status-icon :show-disabled-button="canUpdate" status="warning" /> <status-icon :show-disabled-button="canUpdate" status="warning" />
<div class="media-body"> <div class="media-body">
<div class="float-left"> <div class="float-left">
<span class="gl-font-weight-bold"> <span
:class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
class="gl-font-weight-bold"
>
{{ {{
__("Merge blocked: merge request must be marked as ready. It's still marked as draft.") __("Merge blocked: merge request must be marked as ready. It's still marked as draft.")
}} }}
......
...@@ -357,15 +357,13 @@ export default class MergeRequestStore { ...@@ -357,15 +357,13 @@ export default class MergeRequestStore {
setApprovals(data) { setApprovals(data) {
this.approvals = data; this.approvals = data;
this.isApproved = data.approved || false; this.isApproved = data.approved || false;
this.setState();
} }
// eslint-disable-next-line class-methods-use-this
get hasMergeChecksFailed() { get hasMergeChecksFailed() {
if (!window.gon?.features?.restructuredMrWidget) return false; return false;
return (
this.hasMergeableDiscussionsState ||
(this.onlyAllowMergeIfPipelineSucceeds && this.isPipelineFailed)
);
} }
// Because the state machine doesn't yet handle every state and transition, // Because the state machine doesn't yet handle every state and transition,
......
<script> <script>
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
export default { export default {
...@@ -6,17 +7,23 @@ export default { ...@@ -6,17 +7,23 @@ export default {
components: { components: {
StatusIcon, StatusIcon,
}, },
mixins: [glFeatureFlagMixin()],
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" /> <status-icon show-disabled-button status="warning" />
<div class="media-body"> <div class="media-body">
<strong class="gl-font-weight-bold gl-text-gray-700"> <span
:class="{
'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
}"
class="gl-font-weight-bold gl-text-gray-700"
>
{{ {{
s__('mrWidget|To merge, a Jira issue key must be mentioned in the title or description.') s__('mrWidget|To merge, a Jira issue key must be mentioned in the title or description.')
}} }}
</strong> </span>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { GlButton } from '@gitlab/ui'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
export default { export default {
name: 'MRWidgetPolicyViolation', name: 'MRWidgetPolicyViolation',
components: { components: {
GlButton,
StatusIcon, StatusIcon,
}, },
mixins: [glFeatureFlagMixin()],
}; };
</script> </script>
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<div class="space-children gl-display-flex"> <div class="space-children gl-display-flex">
<status-icon status="warning" /> <status-icon status="warning" show-disabled-button />
<gl-button category="primary" variant="success" disabled size="small">
{{ s__('mrWidget|Merge') }}
</gl-button>
</div> </div>
<div class="media-body"> <div class="media-body">
<strong class="gl-font-weight-bold gl-text-gray-700 gl-pl-2"> <span
:class="{
'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
}"
class="gl-font-weight-bold gl-text-gray-700 gl-pl-2"
>
{{ s__('mrWidget|Merge blocked: denied licenses must be removed.') }} {{ s__('mrWidget|Merge blocked: denied licenses must be removed.') }}
</strong> </span>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue'; import statusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
export default { export default {
...@@ -10,6 +11,7 @@ export default { ...@@ -10,6 +11,7 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [glFeatureFlagMixin()],
props: { props: {
mr: { mr: {
type: Object, type: Object,
...@@ -19,12 +21,17 @@ export default { ...@@ -19,12 +21,17 @@ export default {
}; };
</script> </script>
<template> <template>
<div class="media"> <div class="mr-widget-body media gl-flex-wrap">
<status-icon status="warning" show-disabled-button /> <status-icon status="warning" show-disabled-button />
<div class="media-body"> <div class="media-body">
<span class="bold">{{ <span
__('Merge unavailable: merge requests are read-only in a secondary Geo node.') :class="{
}}</span> 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
}"
class="bold"
>
{{ __('Merge unavailable: merge requests are read-only in a secondary Geo node.') }}
</span>
<a <a
v-gl-tooltip v-gl-tooltip
:href="mr.geoSecondaryHelpPath" :href="mr.geoSecondaryHelpPath"
......
...@@ -83,6 +83,8 @@ export default class MergeRequestStore extends CEMergeRequestStore { ...@@ -83,6 +83,8 @@ export default class MergeRequestStore extends CEMergeRequestStore {
this.approvals = mapApprovalsResponse(data); this.approvals = mapApprovalsResponse(data);
this.approvalsLeft = Boolean(data.approvals_left); this.approvalsLeft = Boolean(data.approvals_left);
this.preventMerge = !this.isApproved; this.preventMerge = !this.isApproved;
this.setState();
} }
setApprovalRules(data) { setApprovalRules(data) {
...@@ -94,6 +96,8 @@ export default class MergeRequestStore extends CEMergeRequestStore { ...@@ -94,6 +96,8 @@ export default class MergeRequestStore extends CEMergeRequestStore {
if (this.hasApprovalsAvailable && this.approvals && this.approvalsLeft) return !this.isApproved; if (this.hasApprovalsAvailable && this.approvals && this.approvalsLeft) return !this.isApproved;
if (this.blockingMergeRequests.total_count > 0) return true;
return super.hasMergeChecksFailed; return super.hasMergeChecksFailed;
} }
......
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import StatusIcon from '~/vue_merge_request_widget/components/mr_widget_status_icon.vue';
import MrWidgetPolicyViolation from 'ee/vue_merge_request_widget/components/states/mr_widget_policy_violation.vue'; import MrWidgetPolicyViolation from 'ee/vue_merge_request_widget/components/states/mr_widget_policy_violation.vue';
describe('EE MrWidgetPolicyViolation', () => { describe('EE MrWidgetPolicyViolation', () => {
let wrapper; let wrapper;
const findButton = () => wrapper.find(GlButton); const findStatusIcon = () => wrapper.findComponent(StatusIcon);
const createComponent = () => { const createComponent = () => {
wrapper = shallowMount(MrWidgetPolicyViolation, {}); wrapper = shallowMount(MrWidgetPolicyViolation, {});
...@@ -22,7 +22,7 @@ describe('EE MrWidgetPolicyViolation', () => { ...@@ -22,7 +22,7 @@ describe('EE MrWidgetPolicyViolation', () => {
it('shows the disabled merge button', () => { it('shows the disabled merge button', () => {
expect(wrapper.text()).toContain('Merge'); expect(wrapper.text()).toContain('Merge');
expect(findButton().props().disabled).toBe(true); expect(findStatusIcon().props('showDisabledButton')).toBe(true);
}); });
it('shows the disabled reason', () => { it('shows the disabled reason', () => {
......
...@@ -42352,6 +42352,9 @@ msgstr "" ...@@ -42352,6 +42352,9 @@ msgstr ""
msgid "mrWidget|Merge blocked: this merge request must be approved." msgid "mrWidget|Merge blocked: this merge request must be approved."
msgstr "" msgstr ""
msgid "mrWidget|Merge blocked: you can only merge once above items are resolved."
msgstr ""
msgid "mrWidget|Merge failed." msgid "mrWidget|Merge failed."
msgstr "" msgstr ""
...@@ -42460,9 +42463,6 @@ msgstr "" ...@@ -42460,9 +42463,6 @@ msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions." msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr "" msgstr ""
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure."
msgstr ""
msgid "mrWidget|The source branch has been deleted" msgid "mrWidget|The source branch has been deleted"
msgstr "" msgstr ""
......
...@@ -15,35 +15,12 @@ describe('Merge request widget merge checks failed state component', () => { ...@@ -15,35 +15,12 @@ describe('Merge request widget merge checks failed state component', () => {
}); });
it.each` it.each`
mrState | displayText mrState | displayText
${{ isPipelineFailed: true }} | ${'pipelineFailed'} ${{ approvals: true, isApproved: false }} | ${'approvalNeeded'}
${{ approvals: true, isApproved: false }} | ${'approvalNeeded'} ${{ blockingMergeRequests: { total_count: 1 } }} | ${'blockingMergeRequests'}
${{ hasMergeableDiscussionsState: true }} | ${'unresolvedDiscussions'}
`('display $displayText text for $mrState', ({ mrState, displayText }) => { `('display $displayText text for $mrState', ({ mrState, displayText }) => {
factory({ mr: mrState }); factory({ mr: mrState });
expect(wrapper.text()).toContain(MergeChecksFailed.i18n[displayText]); expect(wrapper.text()).toContain(MergeChecksFailed.i18n[displayText]);
}); });
describe('unresolved discussions', () => {
it('renders jump to button', () => {
factory({ mr: { hasMergeableDiscussionsState: true } });
expect(wrapper.find('[data-testid="jumpToUnresolved"]').exists()).toBe(true);
});
it('renders resolve thread button', () => {
factory({
mr: {
hasMergeableDiscussionsState: true,
createIssueToResolveDiscussionsPath: 'https://gitlab.com',
},
});
expect(wrapper.find('[data-testid="resolveIssue"]').exists()).toBe(true);
expect(wrapper.find('[data-testid="resolveIssue"]').attributes('href')).toBe(
'https://gitlab.com',
);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment