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>
import { s__, n__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'MRWidgetRelatedLinks',
mixins: [glFeatureFlagMixin()],
props: {
relatedLinks: {
type: Object,
......@@ -14,6 +16,11 @@ export default {
required: false,
default: '',
},
showAssignToMe: {
type: Boolean,
required: false,
default: true,
},
},
computed: {
closesText() {
......@@ -30,16 +37,25 @@ export default {
};
</script>
<template>
<section class="mr-info-list gl-ml-7 gl-pb-5">
<p v-if="relatedLinks.closing">
<section>
<p
v-if="relatedLinks.closing"
:class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
>
{{ closesText }}
<span v-html="relatedLinks.closing /* eslint-disable-line vue/no-v-html */"></span>
</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) }}
<span v-html="relatedLinks.mentioned /* eslint-disable-line vue/no-v-html */"></span>
</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>
</p>
</section>
......
<script>
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
mixins: [glFeatureFlagMixin()],
props: {
value: {
type: String,
......@@ -20,7 +23,10 @@ export default {
<template>
<li>
<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">
<strong>{{ label }}</strong>
</label>
......
<script>
import { GlButton, GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, n__, s__ } from '~/locale';
const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
import { GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
import AddedCommitMessage from '../added_commit_message.vue';
export default {
mergeCommitCount,
components: {
GlButton,
GlSprintf,
AddedCommitMessage,
},
props: {
isSquashEnabled: {
......@@ -39,9 +36,6 @@ export default {
collapseIcon() {
return this.expanded ? 'chevron-down' : 'chevron-right';
},
commitsCountMessage() {
return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
},
modifyLinkMessage() {
if (this.isFastForwardEnabled) return __('Modify commit message');
else if (this.isSquashEnabled) return __('Modify commit messages');
......@@ -50,16 +44,6 @@ export default {
ariaLabel() {
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: {
toggle() {
......@@ -86,17 +70,12 @@ export default {
<span v-if="expanded">{{ __('Collapse') }}</span>
<span v-else>
<span class="vertical-align-middle">
<gl-sprintf :message="message">
<template #commitCount>
<strong class="commits-count-message">{{ commitsCountMessage }}</strong>
</template>
<template #mergeCommitCount>
<strong>{{ $options.mergeCommitCount }}</strong>
</template>
<template #targetBranch>
<span class="label-branch">{{ targetBranchEscaped }}</span>
</template>
</gl-sprintf>
<added-commit-message
:is-squash-enabled="isSquashEnabled"
:is-fast-forward-enabled="isFastForwardEnabled"
:commits-count="commitsCount"
:target-branch="targetBranch"
/>
</span>
<gl-button variant="link" class="modify-message-button">
{{ modifyLinkMessage }}
......
<script>
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
......@@ -6,11 +7,12 @@ export default {
components: {
statusIcon,
},
mixins: [glFeatureFlagMixin()],
};
</script>
<template>
<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">
<span class="bold"> {{ s__('mrWidget|Checking if merge request can be merged…') }} </span>
</div>
......
......@@ -37,7 +37,7 @@ export default {
<template>
<div class="mr-widget-body media">
<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">
{{ __('Ready to merge!') }}
</template>
......
<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';
export default {
components: {
GlIcon,
GlFormCheckbox,
GlLink,
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagsMixin()],
i18n: {
...SQUASH_BEFORE_MERGE,
},
......@@ -33,6 +36,9 @@ export default {
tooltipTitle() {
return this.isDisabled ? this.$options.i18n.tooltipTitle : null;
},
helpIconName() {
return this.glFeatures.restructuredMrWidget ? 'question-o' : 'question';
},
},
};
</script>
......@@ -51,18 +57,18 @@ export default {
>
{{ $options.i18n.checkboxLabel }}
</gl-form-checkbox>
<a
<gl-link
v-if="helpPath"
v-gl-tooltip
:href="helpPath"
:title="$options.i18n.helpLabel"
:class="{ 'gl-text-blue-600': glFeatures.restructuredMrWidget }"
target="_blank"
rel="noopener noreferrer nofollow"
>
<gl-icon name="question" />
<gl-icon :name="helpIconName" />
<span class="sr-only">
{{ $options.i18n.helpLabel }}
</span>
</a>
</gl-link>
</div>
</template>
......@@ -91,6 +91,7 @@ export default {
MrWidgetApprovals,
SecurityReportsApp: () => import('~/vue_shared/security_reports/security_reports_app.vue'),
MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'),
ReadyToMerge: ReadyToMergeState,
},
apollo: {
state: {
......@@ -213,6 +214,9 @@ export default {
window.gon?.features?.refactorMrWidgetsExtensionsUser
);
},
isRestructuredMrWidgetEnabled() {
return window.gon?.features?.restructuredMrWidget;
},
},
watch: {
'mr.machineValue': {
......@@ -547,12 +551,17 @@ export default {
<div class="mr-widget-section">
<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
v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks"
class="mr-info-list gl-ml-7 gl-pb-5"
/>
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
......
......@@ -18,7 +18,9 @@ fragment ReadyToMerge on Project {
commitCount
diffHeadSha
userPermissions {
canMerge
removeSourceBranch
updateMergeRequest
}
targetBranch
mergeError
......
import { stateKey } from './state_maps';
export default function deviseState() {
if (this.hasMergeChecksFailed) {
if (!this.commitsCount) {
return stateKey.nothingToMerge;
} else if (this.hasMergeChecksFailed && !this.autoMergeEnabled) {
return stateKey.mergeChecksFailed;
} else if (this.projectArchived) {
return stateKey.archived;
} else if (this.branchMissing) {
return stateKey.missingBranch;
} else if (!this.commitsCount) {
return stateKey.nothingToMerge;
} else if (this.mergeStatus === 'unchecked' || this.mergeStatus === 'checking') {
return stateKey.checking;
} else if (this.hasConflicts) {
......
......@@ -269,7 +269,9 @@ $tabs-holder-z-index: 250;
}
.mr-widget-body {
line-height: 28px;
&:not(.mr-widget-body-line-height-1) {
line-height: 28px;
}
@include clearfix;
......
......@@ -469,11 +469,17 @@ export default {
<div class="mr-widget-section">
<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
v-if="shouldRenderRelatedLinks"
:state="mr.state"
:related-links="mr.relatedLinks"
class="mr-info-list gl-ml-7 gl-pb-5"
/>
<source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
......
......@@ -92,7 +92,7 @@ export default class MergeRequestStore extends CEMergeRequestStore {
get hasMergeChecksFailed() {
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;
}
......
......@@ -1110,6 +1110,9 @@ msgstr ""
msgid "(check progress)"
msgstr ""
msgid "(commits will be squashed)"
msgstr ""
msgid "(deleted)"
msgstr ""
......@@ -12424,6 +12427,9 @@ msgstr ""
msgid "Edit comment"
msgstr ""
msgid "Edit commit message"
msgstr ""
msgid "Edit deploy freeze"
msgstr ""
......@@ -21588,6 +21594,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
msgid "Merge details"
msgstr ""
msgid "Merge events"
msgstr ""
......@@ -32449,6 +32458,12 @@ msgstr ""
msgid "Source branch"
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}"
msgstr ""
......@@ -40956,7 +40971,7 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}."
msgstr ""
msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
......
......@@ -9,7 +9,7 @@ exports[`New ready to merge state component renders permission text if canMerge
/>
<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.
......@@ -27,7 +27,7 @@ exports[`New ready to merge state component renders permission text if canMerge
/>
<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!
......
import { shallowMount } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
......@@ -6,7 +6,7 @@ describe('Commits header component', () => {
let wrapper;
const createComponent = (props) => {
wrapper = shallowMount(CommitsHeader, {
wrapper = mount(CommitsHeader, {
stubs: {
GlSprintf,
},
......
import { GlFormCheckbox } from '@gitlab/ui';
import { GlFormCheckbox, GlLink } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import SquashBeforeMerge from '~/vue_merge_request_widget/components/states/squash_before_merge.vue';
import { SQUASH_BEFORE_MERGE } from '~/vue_merge_request_widget/i18n';
......@@ -77,7 +77,7 @@ describe('Squash before merge component', () => {
value: false,
});
const aboutLink = wrapper.find('a');
const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.exists()).toBe(false);
});
......@@ -88,7 +88,7 @@ describe('Squash before merge component', () => {
helpPath: 'test-path',
});
const aboutLink = wrapper.find('a');
const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.exists()).toBe(true);
});
......@@ -99,7 +99,7 @@ describe('Squash before merge component', () => {
helpPath: 'test-path',
});
const aboutLink = wrapper.find('a');
const aboutLink = wrapper.findComponent(GlLink);
expect(aboutLink.attributes('href')).toEqual('test-path');
});
......
......@@ -74,6 +74,7 @@ describe('getStateKey', () => {
expect(bound()).toEqual('nothingToMerge');
context.commitsCount = 1;
context.branchMissing = true;
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