Commit 4da6b88b authored by Phil Hughes's avatar Phil Hughes

Updates ready to merge state to always be visible

Moves the ready to merge component out of the state
checker and made visible below the state components.

Updates the design and spacing to match the desired
designs.

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/324162/
parent c1ab52b6
<script>
import { GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { n__, s__ } from '~/locale';
const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
export default {
components: {
GlSprintf,
},
mixins: [glFeatureFlagMixin()],
props: {
isSquashEnabled: {
type: Boolean,
required: false,
default: false,
},
isFastForwardEnabled: {
type: Boolean,
required: true,
},
commitsCount: {
type: Number,
required: false,
default: 0,
},
targetBranch: {
type: String,
required: true,
},
},
computed: {
targetBranchEscaped() {
return escape(this.targetBranch);
},
commitsCountMessage() {
return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
},
message() {
return this.isFastForwardEnabled
? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
: s__(
'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.',
);
},
textDecorativeComponent() {
return this.glFeatures.restructuredMrWidget ? 'span' : 'strong';
},
},
mergeCommitCount,
};
</script>
<template>
<span>
<gl-sprintf :message="message">
<template #commitCount>
<component :is="textDecorativeComponent" class="commits-count-message">{{
commitsCountMessage
}}</component>
</template>
<template #mergeCommitCount>
<component :is="textDecorativeComponent">{{ $options.mergeCommitCount }}</component>
</template>
<template #targetBranch>
<span class="label-branch">{{ targetBranchEscaped }}</span>
</template>
<template v-if="glFeatures.restructuredMrWidget" #squashedCommits>
<template v-if="isSquashEnabled">
{{ __('(commits will be squashed)') }}</template
></template
>
</gl-sprintf>
</span>
</template>
<script> <script>
import { s__, n__ } from '~/locale'; import { s__, n__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
name: 'MRWidgetRelatedLinks', name: 'MRWidgetRelatedLinks',
mixins: [glFeatureFlagMixin()],
props: { props: {
relatedLinks: { relatedLinks: {
type: Object, type: Object,
...@@ -14,6 +16,11 @@ export default { ...@@ -14,6 +16,11 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
showAssignToMe: {
type: Boolean,
required: false,
default: true,
},
}, },
computed: { computed: {
closesText() { closesText() {
...@@ -30,16 +37,25 @@ export default { ...@@ -30,16 +37,25 @@ export default {
}; };
</script> </script>
<template> <template>
<section class="mr-info-list gl-ml-7 gl-pb-5"> <section>
<p v-if="relatedLinks.closing"> <p
v-if="relatedLinks.closing"
:class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
>
{{ closesText }} {{ closesText }}
<span v-html="relatedLinks.closing /* eslint-disable-line vue/no-v-html */"></span> <span v-html="relatedLinks.closing /* eslint-disable-line vue/no-v-html */"></span>
</p> </p>
<p v-if="relatedLinks.mentioned"> <p
v-if="relatedLinks.mentioned"
:class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
>
{{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }} {{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }}
<span v-html="relatedLinks.mentioned /* eslint-disable-line vue/no-v-html */"></span> <span v-html="relatedLinks.mentioned /* eslint-disable-line vue/no-v-html */"></span>
</p> </p>
<p v-if="relatedLinks.assignToMe"> <p
v-if="relatedLinks.assignToMe && showAssignToMe"
:class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
>
<span v-html="relatedLinks.assignToMe /* eslint-disable-line vue/no-v-html */"></span> <span v-html="relatedLinks.assignToMe /* eslint-disable-line vue/no-v-html */"></span>
</p> </p>
</section> </section>
......
<script> <script>
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default { export default {
mixins: [glFeatureFlagMixin()],
props: { props: {
value: { value: {
type: String, type: String,
...@@ -20,7 +23,10 @@ export default { ...@@ -20,7 +23,10 @@ export default {
<template> <template>
<li> <li>
<div class="commit-message-editor"> <div class="commit-message-editor">
<div class="d-flex flex-wrap align-items-center justify-content-between"> <div
:class="{ 'gl-mb-3': glFeatures.restructuredMrWidget }"
class="d-flex flex-wrap align-items-center justify-content-between"
>
<label class="col-form-label" :for="inputId"> <label class="col-form-label" :for="inputId">
<strong>{{ label }}</strong> <strong>{{ label }}</strong>
</label> </label>
......
<script> <script>
import { GlButton, GlSprintf } from '@gitlab/ui'; import { GlButton } from '@gitlab/ui';
import { escape } from 'lodash'; import { __ } from '~/locale';
import { __, n__, s__ } from '~/locale'; import AddedCommitMessage from '../added_commit_message.vue';
const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
export default { export default {
mergeCommitCount,
components: { components: {
GlButton, GlButton,
GlSprintf, AddedCommitMessage,
}, },
props: { props: {
isSquashEnabled: { isSquashEnabled: {
...@@ -39,9 +36,6 @@ export default { ...@@ -39,9 +36,6 @@ export default {
collapseIcon() { collapseIcon() {
return this.expanded ? 'chevron-down' : 'chevron-right'; return this.expanded ? 'chevron-down' : 'chevron-right';
}, },
commitsCountMessage() {
return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
},
modifyLinkMessage() { modifyLinkMessage() {
if (this.isFastForwardEnabled) return __('Modify commit message'); if (this.isFastForwardEnabled) return __('Modify commit message');
else if (this.isSquashEnabled) return __('Modify commit messages'); else if (this.isSquashEnabled) return __('Modify commit messages');
...@@ -50,16 +44,6 @@ export default { ...@@ -50,16 +44,6 @@ export default {
ariaLabel() { ariaLabel() {
return this.expanded ? __('Collapse') : __('Expand'); return this.expanded ? __('Collapse') : __('Expand');
}, },
targetBranchEscaped() {
return escape(this.targetBranch);
},
message() {
return this.isFastForwardEnabled
? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
: s__(
'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}.',
);
},
}, },
methods: { methods: {
toggle() { toggle() {
...@@ -86,17 +70,12 @@ export default { ...@@ -86,17 +70,12 @@ export default {
<span v-if="expanded">{{ __('Collapse') }}</span> <span v-if="expanded">{{ __('Collapse') }}</span>
<span v-else> <span v-else>
<span class="vertical-align-middle"> <span class="vertical-align-middle">
<gl-sprintf :message="message"> <added-commit-message
<template #commitCount> :is-squash-enabled="isSquashEnabled"
<strong class="commits-count-message">{{ commitsCountMessage }}</strong> :is-fast-forward-enabled="isFastForwardEnabled"
</template> :commits-count="commitsCount"
<template #mergeCommitCount> :target-branch="targetBranch"
<strong>{{ $options.mergeCommitCount }}</strong> />
</template>
<template #targetBranch>
<span class="label-branch">{{ targetBranchEscaped }}</span>
</template>
</gl-sprintf>
</span> </span>
<gl-button variant="link" class="modify-message-button"> <gl-button variant="link" class="modify-message-button">
{{ modifyLinkMessage }} {{ modifyLinkMessage }}
......
<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,11 +7,12 @@ export default { ...@@ -6,11 +7,12 @@ 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="loading" /> <status-icon :show-disabled-button="!glFeatures.restructuredMrWidget" 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="bold"> {{ s__('mrWidget|Checking if merge request can be merged…') }} </span>
</div> </div>
......
...@@ -37,7 +37,7 @@ export default { ...@@ -37,7 +37,7 @@ export default {
<template> <template>
<div class="mr-widget-body media"> <div class="mr-widget-body media">
<status-icon status="success" /> <status-icon status="success" />
<p class="media-body gl-m-0! gl-font-weight-bold"> <p class="media-body gl-m-0! gl-font-weight-bold gl-text-gray-900!">
<template v-if="canMerge"> <template v-if="canMerge">
{{ __('Ready to merge!') }} {{ __('Ready to merge!') }}
</template> </template>
......
...@@ -35,6 +35,8 @@ import eventHub from '../../event_hub'; ...@@ -35,6 +35,8 @@ import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables'; import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MergeRequestStore from '../../stores/mr_widget_store'; import MergeRequestStore from '../../stores/mr_widget_store';
import statusIcon from '../mr_widget_status_icon.vue'; import statusIcon from '../mr_widget_status_icon.vue';
import AddedCommitMessage from '../added_commit_message.vue';
import RelatedLinks from '../mr_widget_related_links.vue';
import CommitEdit from './commit_edit.vue'; import CommitEdit from './commit_edit.vue';
import CommitMessageDropdown from './commit_message_dropdown.vue'; import CommitMessageDropdown from './commit_message_dropdown.vue';
import CommitsHeader from './commits_header.vue'; import CommitsHeader from './commits_header.vue';
...@@ -113,6 +115,8 @@ export default { ...@@ -113,6 +115,8 @@ export default {
import( import(
'ee_component/vue_merge_request_widget/components/merge_train_failed_pipeline_confirmation_dialog.vue' 'ee_component/vue_merge_request_widget/components/merge_train_failed_pipeline_confirmation_dialog.vue'
), ),
AddedCommitMessage,
RelatedLinks,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
...@@ -134,6 +138,7 @@ export default { ...@@ -134,6 +138,7 @@ export default {
isSquashReadOnly: this.mr.squashIsReadonly, isSquashReadOnly: this.mr.squashIsReadonly,
squashCommitMessage: this.mr.squashCommitMessage, squashCommitMessage: this.mr.squashCommitMessage,
isPipelineFailedModalVisible: false, isPipelineFailedModalVisible: false,
editCommitMessage: false,
}; };
}, },
computed: { computed: {
...@@ -162,7 +167,7 @@ export default { ...@@ -162,7 +167,7 @@ export default {
}, },
isMergeAllowed() { isMergeAllowed() {
if (this.glFeatures.mergeRequestWidgetGraphql) { if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.mergeable || false; return this.state.mergeable;
} }
return this.mr.isMergeAllowed; return this.mr.isMergeAllowed;
...@@ -279,6 +284,10 @@ export default { ...@@ -279,6 +284,10 @@ export default {
return enableSquashBeforeMerge && this.commitsCount > 1; return enableSquashBeforeMerge && this.commitsCount > 1;
}, },
shouldShowMergeControls() { shouldShowMergeControls() {
if (this.glFeatures.restructuredMrWidget) {
return this.restructuredWidgetShowMergeButtons;
}
return this.isMergeAllowed || this.isAutoMergeAvailable; return this.isMergeAllowed || this.isAutoMergeAvailable;
}, },
shouldShowSquashEdit() { shouldShowSquashEdit() {
...@@ -297,15 +306,26 @@ export default { ...@@ -297,15 +306,26 @@ export default {
showDangerMessageForMergeTrain() { showDangerMessageForMergeTrain() {
return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed; return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed;
}, },
restructuredWidgetShowMergeButtons() {
if (this.glFeatures.restructuredMrWidget) {
return this.isMergeAllowed && this.state.userPermissions.canMerge;
}
return true;
},
}, },
mounted() { mounted() {
if (this.glFeatures.mergeRequestWidgetGraphql) { if (this.glFeatures.mergeRequestWidgetGraphql) {
eventHub.$on('ApprovalUpdated', this.updateGraphqlState); eventHub.$on('ApprovalUpdated', this.updateGraphqlState);
eventHub.$on('MRWidgetUpdateRequested', this.updateGraphqlState);
eventHub.$on('mr.discussion.updated', this.updateGraphqlState);
} }
}, },
beforeDestroy() { beforeDestroy() {
if (this.glFeatures.mergeRequestWidgetGraphql) { if (this.glFeatures.mergeRequestWidgetGraphql) {
eventHub.$off('ApprovalUpdated', this.updateGraphqlState); eventHub.$off('ApprovalUpdated', this.updateGraphqlState);
eventHub.$off('MRWidgetUpdateRequested', this.updateGraphqlState);
eventHub.$off('mr.discussion.updated', this.updateGraphqlState);
} }
if (this.pollingInterval) { if (this.pollingInterval) {
...@@ -492,7 +512,12 @@ export default { ...@@ -492,7 +512,12 @@ export default {
</script> </script>
<template> <template>
<div> <div
:class="{
'gl-border-t-1 gl-border-t-solid gl-border-gray-100 gl-bg-gray-10 gl-pl-7':
glFeatures.restructuredMrWidget,
}"
>
<div v-if="loading" class="mr-widget-body"> <div v-if="loading" class="mr-widget-body">
<div class="gl-w-full mr-ready-to-merge-loader"> <div class="gl-w-full mr-ready-to-merge-loader">
<gl-skeleton-loader :width="418" :height="30"> <gl-skeleton-loader :width="418" :height="30">
...@@ -504,11 +529,16 @@ export default { ...@@ -504,11 +529,16 @@ export default {
</div> </div>
</div> </div>
<template v-else> <template v-else>
<div class="mr-widget-body media"> <div
<status-icon :status="iconClass" /> class="mr-widget-body media"
:class="{
'mr-widget-body-line-height-1': glFeatures.restructuredMrWidget,
}"
>
<status-icon v-if="!glFeatures.restructuredMrWidget" :status="iconClass" />
<div class="media-body"> <div class="media-body">
<div class="mr-widget-body-controls gl-display-flex gl-align-items-center"> <div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap">
<gl-button-group class="gl-align-self-start"> <gl-button-group v-if="restructuredWidgetShowMergeButtons" class="gl-align-self-start">
<gl-button <gl-button
size="medium" size="medium"
category="primary" category="primary"
...@@ -555,6 +585,7 @@ export default { ...@@ -555,6 +585,7 @@ export default {
</gl-button-group> </gl-button-group>
<div <div
v-if="shouldShowMergeControls" v-if="shouldShowMergeControls"
:class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }"
class="gl-display-flex gl-align-items-center gl-flex-wrap" class="gl-display-flex gl-align-items-center gl-flex-wrap"
> >
<merge-train-helper-icon <merge-train-helper-icon
...@@ -570,7 +601,11 @@ export default { ...@@ -570,7 +601,11 @@ export default {
id="remove-source-branch-input" id="remove-source-branch-input"
v-model="removeSourceBranch" v-model="removeSourceBranch"
:disabled="isRemoveSourceBranchButtonDisabled" :disabled="isRemoveSourceBranchButtonDisabled"
class="js-remove-source-branch-checkbox gl-mx-3 gl-display-flex gl-align-items-center" :class="{
'gl-mx-3': !glFeatures.restructuredMrWidget,
'gl-mr-5': glFeatures.restructuredMrWidget,
}"
class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center"
> >
{{ __('Delete source branch') }} {{ __('Delete source branch') }}
</gl-form-checkbox> </gl-form-checkbox>
...@@ -581,11 +616,26 @@ export default { ...@@ -581,11 +616,26 @@ export default {
v-model="squashBeforeMerge" v-model="squashBeforeMerge"
:help-path="mr.squashBeforeMergeHelpPath" :help-path="mr.squashBeforeMergeHelpPath"
:is-disabled="isSquashReadOnly" :is-disabled="isSquashReadOnly"
class="gl-mx-3" :class="{
'gl-mx-3': !glFeatures.restructuredMrWidget,
'gl-mr-5': glFeatures.restructuredMrWidget,
}"
/> />
<gl-form-checkbox
v-if="
glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)
"
v-model="editCommitMessage"
class="gl-display-flex gl-align-items-center"
>
{{ __('Edit commit message') }}
</gl-form-checkbox>
</div> </div>
<template v-else> <div
<div class="bold js-resolve-mr-widget-items-message gl-ml-3"> v-else-if="!glFeatures.restructuredMrWidget"
class="bold js-resolve-mr-widget-items-message gl-ml-3"
>
<div <div
v-if="hasPipelineMustSucceedConflict" v-if="hasPipelineMustSucceedConflict"
class="gl-display-flex gl-align-items-center" class="gl-display-flex gl-align-items-center"
...@@ -602,10 +652,105 @@ export default { ...@@ -602,10 +652,105 @@ export default {
</div> </div>
<gl-sprintf v-else :message="mergeDisabledText" /> <gl-sprintf v-else :message="mergeDisabledText" />
</div> </div>
<template v-if="glFeatures.restructuredMrWidget">
<div v-show="editCommitMessage" class="gl-w-full gl-order-n1">
<ul
:class="{
'content-list': !glFeatures.restructuredMrWidget,
'gl-list-style-none gl-p-0 gl-pt-4': glFeatures.restructuredMrWidget,
}"
class="border-top commits-list flex-list"
>
<commit-edit
v-if="shouldShowSquashEdit"
v-model="squashCommitMessage"
:label="__('Squash commit message')"
input-id="squash-message-edit"
class="gl-m-0! gl-p-0!"
>
<template #header>
<commit-message-dropdown v-model="squashCommitMessage" :commits="commits" />
</template>
</commit-edit>
<commit-edit
v-if="shouldShowMergeEdit"
v-model="commitMessage"
:label="__('Merge commit message')"
input-id="merge-message-edit"
class="gl-m-0! gl-p-0!"
>
<template #checkbox>
<label>
<input
id="include-description"
type="checkbox"
@change="updateMergeCommitMessage($event.target.checked)"
/>
{{ __('Include merge request description') }}
</label>
</template>
</commit-edit>
</ul>
</div>
<div
v-if="!restructuredWidgetShowMergeButtons"
class="gl-w-full gl-order-n1 gl-text-gray-500"
>
<strong>
{{ __('Merge details') }}
</strong>
<ul class="gl-pl-4 gl-m-0">
<li class="gl-line-height-normal">
<added-commit-message
:is-squash-enabled="squashBeforeMerge"
:is-fast-forward-enabled="!shouldShowMergeEdit"
:commits-count="commitsCount"
:target-branch="stateData.targetBranch"
/>
</li>
<li class="gl-line-height-normal">
<template v-if="removeSourceBranch">
{{ __('Source branch will be deleted.') }}
</template>
<template v-else>
{{ __('Source branch will not be deleted.') }}
</template>
</li>
<li v-if="mr.relatedLinks" class="gl-line-height-normal">
<related-links
:state="mr.state"
:related-links="mr.relatedLinks"
:show-assign-to-me="false"
class="mr-ready-merge-related-links gl-display-inline"
/>
</li>
</ul>
</div>
<div
v-else
:class="{ 'gl-mb-5': restructuredWidgetShowMergeButtons }"
class="gl-w-full gl-order-n1 gl-text-gray-500"
>
<added-commit-message
:is-squash-enabled="squashBeforeMerge"
:is-fast-forward-enabled="!shouldShowMergeEdit"
:commits-count="commitsCount"
:target-branch="stateData.targetBranch"
/>
<template v-if="mr.relatedLinks">
&middot;
<related-links
:state="mr.state"
:related-links="mr.relatedLinks"
:show-assign-to-me="false"
class="mr-ready-merge-related-links gl-display-inline"
/>
</template>
</div>
</template> </template>
</div> </div>
<div <div
v-if="showDangerMessageForMergeTrain" v-if="showDangerMessageForMergeTrain && !glFeatures.restructuredMrWidget"
class="gl-mt-5 gl-text-gray-500" class="gl-mt-5 gl-text-gray-500"
data-testid="failed-pipeline-merge-train-text" data-testid="failed-pipeline-merge-train-text"
> >
...@@ -613,7 +758,7 @@ export default { ...@@ -613,7 +758,7 @@ export default {
</div> </div>
</div> </div>
</div> </div>
<template v-if="shouldShowMergeControls"> <template v-if="shouldShowMergeControls && !glFeatures.restructuredMrWidget">
<div <div
v-if="!shouldShowMergeEdit" v-if="!shouldShowMergeEdit"
class="mr-fast-forward-message" class="mr-fast-forward-message"
...@@ -622,7 +767,7 @@ export default { ...@@ -622,7 +767,7 @@ export default {
{{ __('Fast-forward merge without a merge commit') }} {{ __('Fast-forward merge without a merge commit') }}
</div> </div>
<commits-header <commits-header
v-if="shouldShowSquashEdit || shouldShowMergeEdit" v-if="!glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)"
:is-squash-enabled="squashBeforeMerge" :is-squash-enabled="squashBeforeMerge"
:commits-count="commitsCount" :commits-count="commitsCount"
:target-branch="stateData.targetBranch" :target-branch="stateData.targetBranch"
......
<script> <script>
import { GlIcon, GlTooltipDirective, GlFormCheckbox } from '@gitlab/ui'; import { GlIcon, GlTooltipDirective, GlFormCheckbox, GlLink } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SQUASH_BEFORE_MERGE } from '../../i18n'; import { SQUASH_BEFORE_MERGE } from '../../i18n';
export default { export default {
components: { components: {
GlIcon, GlIcon,
GlFormCheckbox, GlFormCheckbox,
GlLink,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [glFeatureFlagsMixin()],
i18n: { i18n: {
...SQUASH_BEFORE_MERGE, ...SQUASH_BEFORE_MERGE,
}, },
...@@ -33,6 +36,9 @@ export default { ...@@ -33,6 +36,9 @@ export default {
tooltipTitle() { tooltipTitle() {
return this.isDisabled ? this.$options.i18n.tooltipTitle : null; return this.isDisabled ? this.$options.i18n.tooltipTitle : null;
}, },
helpIconName() {
return this.glFeatures.restructuredMrWidget ? 'question-o' : 'question';
},
}, },
}; };
</script> </script>
...@@ -51,18 +57,18 @@ export default { ...@@ -51,18 +57,18 @@ export default {
> >
{{ $options.i18n.checkboxLabel }} {{ $options.i18n.checkboxLabel }}
</gl-form-checkbox> </gl-form-checkbox>
<a <gl-link
v-if="helpPath" v-if="helpPath"
v-gl-tooltip v-gl-tooltip
:href="helpPath" :href="helpPath"
:title="$options.i18n.helpLabel" :title="$options.i18n.helpLabel"
:class="{ 'gl-text-blue-600': glFeatures.restructuredMrWidget }"
target="_blank" target="_blank"
rel="noopener noreferrer nofollow"
> >
<gl-icon name="question" /> <gl-icon :name="helpIconName" />
<span class="sr-only"> <span class="sr-only">
{{ $options.i18n.helpLabel }} {{ $options.i18n.helpLabel }}
</span> </span>
</a> </gl-link>
</div> </div>
</template> </template>
...@@ -91,6 +91,7 @@ export default { ...@@ -91,6 +91,7 @@ export default {
MrWidgetApprovals, MrWidgetApprovals,
SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'), SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'),
MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'), MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'),
ReadyToMerge: ReadyToMergeState,
}, },
apollo: { apollo: {
state: { state: {
...@@ -213,6 +214,9 @@ export default { ...@@ -213,6 +214,9 @@ export default {
window.gon?.features?.refactorMrWidgetsExtensionsUser window.gon?.features?.refactorMrWidgetsExtensionsUser
); );
}, },
isRestructuredMrWidgetEnabled() {
return window.gon?.features?.restructuredMrWidget;
},
}, },
watch: { watch: {
'mr.machineValue': { 'mr.machineValue': {
...@@ -547,12 +551,17 @@ export default { ...@@ -547,12 +551,17 @@ export default {
<div class="mr-widget-section"> <div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" /> <component :is="componentName" :mr="mr" :service="service" />
<ready-to-merge
<div class="mr-widget-info"> v-if="isRestructuredMrWidgetEnabled && mr.commitsCount"
:mr="mr"
:service="service"
/>
<div v-else class="mr-widget-info">
<mr-widget-related-links <mr-widget-related-links
v-if="shouldRenderRelatedLinks" v-if="shouldRenderRelatedLinks"
:state="mr.state" :state="mr.state"
:related-links="mr.relatedLinks" :related-links="mr.relatedLinks"
class="mr-info-list gl-ml-7 gl-pb-5"
/> />
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" /> <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
......
...@@ -18,7 +18,9 @@ fragment ReadyToMerge on Project { ...@@ -18,7 +18,9 @@ fragment ReadyToMerge on Project {
commitCount commitCount
diffHeadSha diffHeadSha
userPermissions { userPermissions {
canMerge
removeSourceBranch removeSourceBranch
updateMergeRequest
} }
targetBranch targetBranch
mergeError mergeError
......
import { stateKey } from './state_maps'; import { stateKey } from './state_maps';
export default function deviseState() { export default function deviseState() {
if (this.hasMergeChecksFailed) { if (!this.commitsCount) {
return stateKey.nothingToMerge;
} else if (this.hasMergeChecksFailed && !this.autoMergeEnabled) {
return stateKey.mergeChecksFailed; return stateKey.mergeChecksFailed;
} else if (this.projectArchived) { } else if (this.projectArchived) {
return stateKey.archived; return stateKey.archived;
} else if (this.branchMissing) { } else if (this.branchMissing) {
return stateKey.missingBranch; return stateKey.missingBranch;
} else if (!this.commitsCount) {
return stateKey.nothingToMerge;
} else if (this.mergeStatus === 'unchecked' || this.mergeStatus === 'checking') { } else if (this.mergeStatus === 'unchecked' || this.mergeStatus === 'checking') {
return stateKey.checking; return stateKey.checking;
} else if (this.hasConflicts) { } else if (this.hasConflicts) {
......
...@@ -269,7 +269,9 @@ $tabs-holder-z-index: 250; ...@@ -269,7 +269,9 @@ $tabs-holder-z-index: 250;
} }
.mr-widget-body { .mr-widget-body {
&:not(.mr-widget-body-line-height-1) {
line-height: 28px; line-height: 28px;
}
@include clearfix; @include clearfix;
......
...@@ -469,11 +469,17 @@ export default { ...@@ -469,11 +469,17 @@ export default {
<div class="mr-widget-section"> <div class="mr-widget-section">
<component :is="componentName" :mr="mr" :service="service" /> <component :is="componentName" :mr="mr" :service="service" />
<div class="mr-widget-info"> <ready-to-merge
v-if="isRestructuredMrWidgetEnabled && mr.commitsCount"
:mr="mr"
:service="service"
/>
<div v-else class="mr-widget-info">
<mr-widget-related-links <mr-widget-related-links
v-if="shouldRenderRelatedLinks" v-if="shouldRenderRelatedLinks"
:state="mr.state" :state="mr.state"
:related-links="mr.relatedLinks" :related-links="mr.relatedLinks"
class="mr-info-list gl-ml-7 gl-pb-5"
/> />
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" /> <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
......
...@@ -92,7 +92,7 @@ export default class MergeRequestStore extends CEMergeRequestStore { ...@@ -92,7 +92,7 @@ export default class MergeRequestStore extends CEMergeRequestStore {
get hasMergeChecksFailed() { get hasMergeChecksFailed() {
if (!window.gon?.features?.restructuredMrWidget) return false; if (!window.gon?.features?.restructuredMrWidget) return false;
if (this.hasApprovalsAvailable) return !this.isApproved; if (this.hasApprovalsAvailable && this.approvals && this.approvalsLeft) return !this.isApproved;
return super.hasMergeChecksFailed; return super.hasMergeChecksFailed;
} }
......
...@@ -1110,6 +1110,9 @@ msgstr "" ...@@ -1110,6 +1110,9 @@ msgstr ""
msgid "(check progress)" msgid "(check progress)"
msgstr "" msgstr ""
msgid "(commits will be squashed)"
msgstr ""
msgid "(deleted)" msgid "(deleted)"
msgstr "" msgstr ""
...@@ -12424,6 +12427,9 @@ msgstr "" ...@@ -12424,6 +12427,9 @@ msgstr ""
msgid "Edit comment" msgid "Edit comment"
msgstr "" msgstr ""
msgid "Edit commit message"
msgstr ""
msgid "Edit deploy freeze" msgid "Edit deploy freeze"
msgstr "" msgstr ""
...@@ -21588,6 +21594,9 @@ msgstr "" ...@@ -21588,6 +21594,9 @@ msgstr ""
msgid "Merge commit message" msgid "Merge commit message"
msgstr "" msgstr ""
msgid "Merge details"
msgstr ""
msgid "Merge events" msgid "Merge events"
msgstr "" msgstr ""
...@@ -32449,6 +32458,12 @@ msgstr "" ...@@ -32449,6 +32458,12 @@ msgstr ""
msgid "Source branch" msgid "Source branch"
msgstr "" msgstr ""
msgid "Source branch will be deleted."
msgstr ""
msgid "Source branch will not be deleted."
msgstr ""
msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}" msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
msgstr "" msgstr ""
...@@ -40956,7 +40971,7 @@ msgstr "" ...@@ -40956,7 +40971,7 @@ msgstr ""
msgid "most recent deployment" msgid "most recent deployment"
msgstr "" msgstr ""
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}." msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}."
msgstr "" msgstr ""
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}." msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
......
...@@ -9,7 +9,7 @@ exports[`New ready to merge state component renders permission text if canMerge ...@@ -9,7 +9,7 @@ exports[`New ready to merge state component renders permission text if canMerge
/> />
<p <p
class="media-body gl-m-0! gl-font-weight-bold" class="media-body gl-m-0! gl-font-weight-bold gl-text-gray-900!"
> >
Ready to merge by members who can write to the target branch. Ready to merge by members who can write to the target branch.
...@@ -27,7 +27,7 @@ exports[`New ready to merge state component renders permission text if canMerge ...@@ -27,7 +27,7 @@ exports[`New ready to merge state component renders permission text if canMerge
/> />
<p <p
class="media-body gl-m-0! gl-font-weight-bold" class="media-body gl-m-0! gl-font-weight-bold gl-text-gray-900!"
> >
Ready to merge! Ready to merge!
......
import { shallowMount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui'; import { GlSprintf } from '@gitlab/ui';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue'; import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
...@@ -6,7 +6,7 @@ describe('Commits header component', () => { ...@@ -6,7 +6,7 @@ describe('Commits header component', () => {
let wrapper; let wrapper;
const createComponent = (props) => { const createComponent = (props) => {
wrapper = shallowMount(CommitsHeader, { wrapper = mount(CommitsHeader, {
stubs: { stubs: {
GlSprintf, GlSprintf,
}, },
......
import { GlFormCheckbox } from '@gitlab/ui'; import { GlFormCheckbox, GlLink } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue'; import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
import { SQUASH_BEFORE_MERGE } from '~/vue_merge_request_widget/i18n'; import { SQUASH_BEFORE_MERGE } from '~/vue_merge_request_widget/i18n';
...@@ -77,7 +77,7 @@ describe('Squash before merge component', () => { ...@@ -77,7 +77,7 @@ describe('Squash before merge component', () => {
value: false, value: false,
}); });
const aboutLink = wrapper.find('a'); const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.exists()).toBe(false); expect(aboutLink.exists()).toBe(false);
}); });
...@@ -88,7 +88,7 @@ describe('Squash before merge component', () => { ...@@ -88,7 +88,7 @@ describe('Squash before merge component', () => {
helpPath: 'test-path', helpPath: 'test-path',
}); });
const aboutLink = wrapper.find('a'); const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.exists()).toBe(true); expect(aboutLink.exists()).toBe(true);
}); });
...@@ -99,7 +99,7 @@ describe('Squash before merge component', () => { ...@@ -99,7 +99,7 @@ describe('Squash before merge component', () => {
helpPath: 'test-path', helpPath: 'test-path',
}); });
const aboutLink = wrapper.find('a'); const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.attributes('href')).toEqual('test-path'); expect(aboutLink.attributes('href')).toEqual('test-path');
}); });
......
...@@ -74,6 +74,7 @@ describe('getStateKey', () => { ...@@ -74,6 +74,7 @@ describe('getStateKey', () => {
expect(bound()).toEqual('nothingToMerge'); expect(bound()).toEqual('nothingToMerge');
context.commitsCount = 1;
context.branchMissing = true; context.branchMissing = true;
expect(bound()).toEqual('missingBranch'); expect(bound()).toEqual('missingBranch');
......
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