summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_merge_request_widget
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget')
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue (renamed from app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue)12
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue85
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue18
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue34
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue20
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/state_container.vue55
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue94
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue44
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue65
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue168
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue141
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue345
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue33
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue53
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue29
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue27
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue158
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js12
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue50
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js14
39 files changed, 759 insertions, 835 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
index b76d5d90ead..38f40e8a3c8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/actions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/action_buttons.vue
@@ -14,7 +14,8 @@ export default {
props: {
widget: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
tertiaryButtons: {
type: Array,
@@ -30,6 +31,8 @@ export default {
},
computed: {
dropdownLabel() {
+ if (!this.widget) return undefined;
+
return sprintf(__('%{widget} options'), { widget: this.widget });
},
},
@@ -85,6 +88,7 @@ export default {
:href="btn.href"
:target="btn.target"
:data-clipboard-text="btn.dataClipboardText"
+ :data-method="btn.dataMethod"
@click="onClickAction(btn)"
>
{{ btn.text }}
@@ -99,11 +103,15 @@ export default {
:title="setTooltip(btn)"
:href="btn.href"
:target="btn.target"
- :class="{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }"
+ :class="[{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }, btn.class]"
:data-clipboard-text="btn.dataClipboardText"
+ :data-qa-selector="btn.dataQaSelector"
+ :data-method="btn.dataMethod"
:icon="btn.icon"
:data-testid="btn.testId || 'extension-actions-button'"
:variant="btn.variant || 'confirm'"
+ :loading="btn.loading"
+ :disabled="btn.loading"
category="tertiary"
size="small"
class="gl-display-none gl-md-display-block gl-float-left"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
index 437d035fbf5..254b280bf14 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/added_commit_message.vue
@@ -2,9 +2,9 @@
import { GlSprintf } from '@gitlab/ui';
import { escape } from 'lodash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { n__, s__ } from '~/locale';
+import { n__, s__, sprintf } from '~/locale';
-const mergeCommitCount = s__('mrWidgetCommitsAdded|1 merge commit');
+const mergeCommitCount = s__('mrWidgetCommitsAdded|%{strongStart}1%{strongEnd} merge commit');
export default {
components: {
@@ -49,40 +49,45 @@ export default {
return escape(this.targetBranch);
},
commitsCountMessage() {
- return n__('%d commit', '%d commits', this.isSquashEnabled ? 1 : this.commitsCount);
+ const count = this.isSquashEnabled ? 1 : this.commitsCount;
+
+ return sprintf(
+ n__(
+ '%{strongStart}%{count}%{strongEnd} commit',
+ '%{strongStart}%{count}%{strongEnd} commits',
+ count,
+ ),
+ { count },
+ );
},
message() {
- if (this.glFeatures.restructuredMrWidget) {
- if (this.state === 'closed') {
- return s__('mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}.');
- } else if (this.isMerged) {
- return s__(
- 'mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}.',
- );
- }
-
- return this.isFastForwardEnabled
- ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
- : s__(
- 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.',
- );
+ if (this.state === 'closed') {
+ return s__('mrWidgetCommitsAdded|The changes were not merged into %{targetBranch}.');
+ } else if (this.isMerged) {
+ return s__(
+ 'mrWidgetCommitsAdded|Changes merged into %{targetBranch} with %{mergeCommitSha}%{squashedCommits}.',
+ );
}
return this.isFastForwardEnabled
- ? s__('mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}.')
+ ? s__('mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}.')
: s__(
- 'mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}.',
+ 'mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}%{squashedCommits}.',
);
},
- textDecorativeComponent() {
- return this.glFeatures.restructuredMrWidget ? 'span' : 'strong';
- },
squashCommitMessage() {
if (this.isMerged) {
- return s__('mergedCommitsAdded|(commits were squashed)');
+ return s__('mergedCommitsAdded| (commits were squashed)');
}
- return n__('(squashes %d commit)', '(squashes %d commits)', this.commitsCount);
+ return sprintf(
+ n__(
+ ' (squashes %{strongStart}%{count}%{strongEnd} commit)',
+ ' (squashes %{strongStart}%{count}%{strongEnd} commits)',
+ this.commitsCount,
+ ),
+ { count: this.commitsCount },
+ );
},
},
mergeCommitCount,
@@ -93,25 +98,33 @@ export default {
<span>
<gl-sprintf :message="message">
<template #commitCount>
- <component :is="textDecorativeComponent" class="commits-count-message">{{
- commitsCountMessage
- }}</component>
+ <gl-sprintf :message="commitsCountMessage">
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ </gl-sprintf>
</template>
<template #mergeCommitCount>
- <component :is="textDecorativeComponent">{{ $options.mergeCommitCount }}</component>
+ <gl-sprintf :message="$options.mergeCommitCount">
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ </gl-sprintf>
</template>
<template #targetBranch>
- <span class="label-branch">{{ targetBranchEscaped }}</span>
+ <span class="label-branch gl-font-weight-bold">{{ targetBranchEscaped }}</span>
</template>
<template #squashedCommits>
- <template v-if="glFeatures.restructuredMrWidget && isSquashEnabled">
- {{ squashCommitMessage }}</template
- ></template
- >
+ <template v-if="isSquashEnabled">
+ <gl-sprintf :message="squashCommitMessage">
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold">{{ content }}</span>
+ </template>
+ </gl-sprintf>
+ </template>
+ </template>
<template #mergeCommitSha>
- <template v-if="glFeatures.restructuredMrWidget"
- ><span class="label-branch">{{ mergeCommitSha }}</span></template
- >
+ <span class="label-branch">{{ mergeCommitSha }}</span>
</template>
</gl-sprintf>
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
index 4163d195e0f..f782c28ea19 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue
@@ -4,9 +4,6 @@ import createFlash from '~/flash';
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__, __ } from '~/locale';
-import sidebarEventHub from '~/sidebar/event_hub';
-import showToast from '~/vue_shared/plugins/global_toast';
-import SidebarMediator from '~/sidebar/sidebar_mediator';
import eventHub from '../../event_hub';
import approvalsMixin from '../../mixins/approvals';
import MrWidgetContainer from '../mr_widget_container.vue';
@@ -192,16 +189,8 @@ export default {
.then((data) => {
this.mr.setApprovals(data);
- if (
- this.glFeatures.mrAttentionRequests &&
- SidebarMediator.singleton?.store.currentUserHasAttention
- ) {
- showToast(__('Approved. Your attention request was removed.'));
- }
-
eventHub.$emit('MRWidgetUpdateRequested');
eventHub.$emit('ApprovalUpdated');
- sidebarEventHub.$emit('removeCurrentUserAttentionRequested');
this.$emit('updated');
})
.catch(errFn)
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
index bb1837399ed..1256b3a8e52 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
@@ -80,22 +80,26 @@ export default {
},
computeGraphData(metrics, deploymentTime) {
this.loadingMetrics = false;
- const { memory_before, memory_after, memory_values } = metrics;
+ const {
+ memory_before: memoryBefore,
+ memory_after: memoryAfter,
+ memory_values: memoryValues,
+ } = metrics;
// Both `memory_before` and `memory_after` objects
// have peculiar structure where accessing only a specific
// index yeilds correct value that we can use to show memory delta.
- if (memory_before.length > 0) {
- this.memoryFrom = this.getMegabytes(memory_before[0].value[1]);
+ if (memoryBefore.length > 0) {
+ this.memoryFrom = this.getMegabytes(memoryBefore[0].value[1]);
}
- if (memory_after.length > 0) {
- this.memoryTo = this.getMegabytes(memory_after[0].value[1]);
+ if (memoryAfter.length > 0) {
+ this.memoryTo = this.getMegabytes(memoryAfter[0].value[1]);
}
- if (memory_values.length > 0) {
+ if (memoryValues.length > 0) {
this.hasMetrics = true;
- this.memoryMetrics = memory_values[0].values;
+ this.memoryMetrics = memoryValues[0].values;
this.deploymentTime = deploymentTime;
}
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md b/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md
new file mode 100644
index 00000000000..45ebafec8bf
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/README.md
@@ -0,0 +1 @@
+Please see [the Widget Extensions documentation](development/merge_request_concepts/widget_extensions.md) for necessary information regarding development of new MR Widgets.
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
index 410331004e4..414c5bf9691 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -12,8 +12,8 @@ import { sprintf, s__, __ } from '~/locale';
import Poll from '~/lib/utils/poll';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
+import Actions from '../action_buttons.vue';
import StatusIcon from './status_icon.vue';
-import Actions from './actions.vue';
import ChildContent from './child_content.vue';
import { createTelemetryHub } from './telemetry';
import { generateText } from './utils';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue
index 38f83a61b30..1eccc7de660 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/child_content.vue
@@ -1,7 +1,7 @@
<script>
import { GlBadge, GlLink, GlSafeHtmlDirective, GlModalDirective } from '@gitlab/ui';
+import Actions from '../action_buttons.vue';
import StatusIcon from './status_icon.vue';
-import Actions from './actions.vue';
import { generateText } from './utils';
export default {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js
index b551cd2fd60..bc84459e298 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/telemetry.js
@@ -34,6 +34,36 @@ const nonStandardEvents = {
},
counter: {},
},
+ metrics: {
+ uniqueUser: {
+ expand: ['i_testing_metrics_report_widget_total'],
+ },
+ counter: {},
+ },
+ browserPerformance: {
+ uniqueUser: {
+ expand: ['i_testing_web_performance_widget_total'],
+ },
+ counter: {},
+ },
+ licenseCompliance: {
+ uniqueUser: {
+ expand: ['i_testing_license_compliance_widget_total'],
+ },
+ counter: {},
+ },
+ loadPerformance: {
+ uniqueUser: {
+ expand: ['i_testing_load_performance_widget_total'],
+ },
+ counter: {},
+ },
+ statusChecks: {
+ uniqueUser: {
+ expand: ['i_testing_status_checks_widget'],
+ },
+ counter: {},
+ },
};
function combineDeepArray(path, ...objects) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index 913aa0e1e34..94a1b805b99 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -1,7 +1,6 @@
<script>
-import { GlSafeHtmlDirective as SafeHtml, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlSafeHtmlDirective as SafeHtml, GlLink } from '@gitlab/ui';
import { s__, n__ } from '~/locale';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'MRWidgetRelatedLinks',
@@ -10,9 +9,7 @@ export default {
},
components: {
GlLink,
- GlSprintf,
},
- mixins: [glFeatureFlagMixin()],
props: {
relatedLinks: {
type: Object,
@@ -67,42 +64,21 @@ export default {
</script>
<template>
<section>
- <p
- v-if="relatedLinks.closing"
- :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }"
- >
+ <p v-if="relatedLinks.closing" class="gl-display-inline gl-m-0">
{{ closesText }}
<span v-safe-html="relatedLinks.closing"></span>
</p>
- <p
- v-if="relatedLinks.mentioned"
- :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }"
- >
- <span v-if="relatedLinks.closing && glFeatures.restructuredMrWidget">&middot;</span>
+ <p v-if="relatedLinks.mentioned" class="gl-display-inline gl-m-0">
+ <span v-if="relatedLinks.closing">&middot;</span>
{{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }}
<span v-safe-html="relatedLinks.mentioned"></span>
</p>
- <p
- v-if="shouldShowAssignToMeLink"
- :class="{ 'gl-display-inline gl-m-0': glFeatures.restructuredMrWidget }"
- >
+ <p v-if="shouldShowAssignToMeLink" class="gl-display-inline gl-m-0">
<span>
<gl-link rel="nofollow" data-method="post" :href="relatedLinks.assignToMe">{{
assignIssueText
}}</gl-link>
</span>
</p>
- <div
- v-if="divergedCommitsCount > 0 && !glFeatures.restructuredMrWidget"
- class="diverged-commits-count"
- >
- <gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')">
- <template #link>
- <gl-link :href="targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </div>
</section>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
index 7ff1eb6e73a..5b8acb4ebf8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
@@ -1,25 +1,17 @@
<script>
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { GlLoadingIcon } from '@gitlab/ui';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
export default {
components: {
ciIcon,
- GlButton,
GlLoadingIcon,
},
- mixins: [glFeatureFlagMixin()],
props: {
status: {
type: String,
required: true,
},
- showDisabledButton: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
isLoading() {
@@ -42,15 +34,5 @@ export default {
</div>
<ci-icon v-else :status="statusObj" :size="24" />
</div>
-
- <gl-button
- v-if="!glFeatures.restructuredMrWidget && showDisabledButton"
- category="primary"
- variant="confirm"
- data-testid="disabled-merge-button"
- :disabled="true"
- >
- {{ s__('mrWidget|Merge') }}
- </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue
new file mode 100644
index 00000000000..4a5a03fb598
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/state_container.vue
@@ -0,0 +1,55 @@
+<script>
+import StatusIcon from './mr_widget_status_icon.vue';
+import Actions from './action_buttons.vue';
+
+export default {
+ components: {
+ StatusIcon,
+ Actions,
+ },
+ props: {
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ status: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ actions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="mr-widget-body media">
+ <div v-if="isLoading" class="gl-w-full mr-conflict-loader">
+ <slot name="loading"></slot>
+ </div>
+ <template v-else>
+ <slot name="icon">
+ <status-icon :status="status" />
+ </slot>
+ <div
+ :class="{ 'gl-display-flex': actions.length, 'gl-md-display-flex': !actions.length }"
+ class="media-body"
+ >
+ <slot></slot>
+ <div
+ :class="{ 'gl-flex-direction-column-reverse': !actions.length }"
+ class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto gl-mt-1"
+ >
+ <slot name="actions">
+ <actions v-if="actions.length" :tertiary-buttons="actions" />
+ </slot>
+ </div>
+ </div>
+ </template>
+ </div>
+</template>
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 18761d04c2e..515a7cf51a1 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
@@ -1,8 +1,5 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
export default {
- mixins: [glFeatureFlagMixin()],
props: {
value: {
type: String,
@@ -23,10 +20,7 @@ export default {
<template>
<li>
<div class="commit-message-editor">
- <div
- :class="{ 'gl-mb-3': glFeatures.restructuredMrWidget }"
- class="d-flex flex-wrap align-items-center justify-content-between"
- >
+ <div class="d-flex flex-wrap align-items-center justify-content-between gl-mb-3">
<label class="col-form-label" :for="inputId">
<strong>{{ label }}</strong>
</label>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
index 071920856a8..f74826f95d3 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
@@ -1,5 +1,4 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -7,7 +6,6 @@ export default {
components: {
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
};
</script>
<template>
@@ -16,7 +14,7 @@ export default {
<status-icon status="warning" show-disabled-button />
</div>
<div class="media-body">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
{{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }}
</span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
index aabbeac564a..690acc9a6dc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue
@@ -1,15 +1,15 @@
<script>
-import { GlSkeletonLoader, GlIcon, GlButton, GlSprintf } from '@gitlab/ui';
+import { GlSkeletonLoader, GlIcon, GlSprintf } from '@gitlab/ui';
import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
import autoMergeEnabledQuery from 'ee_else_ce/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql';
import createFlash from '~/flash';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { AUTO_MERGE_STRATEGIES } from '../../constants';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MrWidgetAuthor from '../mr_widget_author.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetAutoMergeEnabled',
@@ -29,8 +29,8 @@ export default {
MrWidgetAuthor,
GlSkeletonLoader,
GlIcon,
- GlButton,
GlSprintf,
+ StateContainer,
},
mixins: [autoMergeMixin, glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
@@ -78,18 +78,25 @@ export default {
autoMergeStrategy() {
return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).autoMergeStrategy;
},
- canRemoveSourceBranch() {
- const { currentUserId } = this.mr;
- const mergeUserId = this.glFeatures.mergeRequestWidgetGraphql
- ? getIdFromGraphQLId(this.state.mergeUser?.id)
- : this.mr.mergeUserId;
- const canRemoveSourceBranch = this.glFeatures.mergeRequestWidgetGraphql
- ? this.state.userPermissions.removeSourceBranch
- : this.mr.canRemoveSourceBranch;
+ actions() {
+ const actions = [];
- return (
- !this.shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId
- );
+ if (this.loading) {
+ return actions;
+ }
+
+ if (this.mr.canCancelAutomaticMerge) {
+ actions.push({
+ text: this.cancelButtonText,
+ loading: this.isCancellingAutoMerge,
+ dataQaSelector: 'cancel_auto_merge_button',
+ class: 'js-cancel-auto-merge',
+ testId: 'cancelAutomaticMergeButton',
+ onClick: () => this.cancelAutomaticMerge(),
+ });
+ }
+
+ return actions;
},
},
methods: {
@@ -144,56 +151,25 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <div v-if="loading" class="gl-w-full mr-conflict-loader">
+ <state-container status="scheduled" :is-loading="loading" :actions="actions">
+ <template #loading>
<gl-skeleton-loader :width="334" :height="30">
<rect x="0" y="3" width="24" height="24" rx="4" />
<rect x="32" y="7" width="150" height="16" rx="4" />
<rect x="190" y="7" width="144" height="16" rx="4" />
</gl-skeleton-loader>
- </div>
- <template v-else>
+ </template>
+ <template v-if="!loading">
+ <h4 class="gl-mr-3" data-testid="statusText">
+ <gl-sprintf :message="statusText" data-testid="statusText">
+ <template #merge_author>
+ <mr-widget-author :author="mergeUser" />
+ </template>
+ </gl-sprintf>
+ </h4>
+ </template>
+ <template v-if="!loading" #icon>
<gl-icon name="status_scheduled" :size="24" class="gl-text-blue-500 gl-mr-3 gl-mt-1" />
- <div class="media-body">
- <h4 class="gl-display-flex">
- <span class="gl-mr-3">
- <gl-sprintf :message="statusText" data-testid="statusText">
- <template #merge_author>
- <mr-widget-author :author="mergeUser" />
- </template>
- </gl-sprintf>
- </span>
- <gl-button
- v-if="mr.canCancelAutomaticMerge"
- :loading="isCancellingAutoMerge"
- size="small"
- class="js-cancel-auto-merge"
- data-qa-selector="cancel_auto_merge_button"
- data-testid="cancelAutomaticMergeButton"
- @click="cancelAutomaticMerge"
- >
- {{ cancelButtonText }}
- </gl-button>
- </h4>
- <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list">
- <p v-if="shouldRemoveSourceBranch">
- {{ s__('mrWidget|Deletes the source branch') }}
- </p>
- <p v-else class="gl-display-flex">
- <span class="gl-mr-3">{{ s__('mrWidget|Does not delete the source branch') }}</span>
- <gl-button
- v-if="canRemoveSourceBranch"
- :loading="isRemovingSourceBranch"
- size="small"
- class="js-remove-source-branch"
- data-testid="removeSourceBranchButton"
- @click="removeSourceBranch"
- >
- {{ s__('mrWidget|Delete source branch') }}
- </gl-button>
- </p>
- </section>
- </div>
</template>
- </div>
+ </state-container>
</template>
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 1a764d3d091..b0cda85f361 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
@@ -1,17 +1,15 @@
<script>
-import { GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import autoMergeFailedQuery from '../../queries/states/auto_merge_failed.query.graphql';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetAutoMergeFailed',
components: {
- statusIcon,
- GlLoadingIcon,
- GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
@@ -38,6 +36,17 @@ export default {
isRefreshing: false,
};
},
+ computed: {
+ actions() {
+ return [
+ {
+ text: s__('mrWidget|Refresh'),
+ loading: this.isRefreshing,
+ onClick: () => this.refreshWidget(),
+ },
+ ];
+ },
+ },
methods: {
refreshWidget() {
this.isRefreshing = true;
@@ -49,23 +58,10 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon status="warning" />
- <div class="media-body space-children gl-display-flex gl-flex-wrap gl-align-items-center">
- <span class="bold">
- <template v-if="mergeError">{{ mergeError }}</template>
- {{ s__('mrWidget|This merge request failed to be merged automatically') }}
- </span>
- <gl-button
- :disabled="isRefreshing"
- category="secondary"
- variant="default"
- size="small"
- @click="refreshWidget"
- >
- <gl-loading-icon v-if="isRefreshing" size="sm" :inline="true" />
- {{ s__('mrWidget|Refresh') }}
- </gl-button>
- </div>
- </div>
+ <state-container status="warning" :actions="actions">
+ <span class="bold gl-ml-0!">
+ <template v-if="mergeError">{{ mergeError }}</template>
+ {{ s__('mrWidget|This merge request failed to be merged automatically') }}
+ </span>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
index fd42fa0421f..e2d87d8d536 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
@@ -1,5 +1,4 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import statusIcon from '../mr_widget_status_icon.vue';
export default {
@@ -7,14 +6,13 @@ export default {
components: {
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
};
</script>
<template>
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="loading" />
<div class="media-body space-children">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
{{ s__('mrWidget|Checking if merge request can be merged…') }}
</span>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
index d50e52f5ac1..61f7d26f51e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
@@ -1,5 +1,4 @@
<script>
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -9,7 +8,6 @@ export default {
MrWidgetAuthorTime,
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
props: {
/* TODO: This is providing all store and service down when it
only needs metrics and targetBranch */
@@ -30,13 +28,6 @@ export default {
:date-title="mr.metrics.closedAt"
:date-readable="mr.metrics.readableClosedAt"
/>
-
- <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list">
- <p>
- {{ s__('mrWidget|The changes were not merged into') }}
- <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
- </p>
- </section>
</div>
</div>
</template>
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 def30dacf8a..8abd915b93e 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
@@ -4,14 +4,14 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import userPermissionsQuery from '../../queries/permissions.query.graphql';
import conflictsStateQuery from '../../queries/states/conflicts.query.graphql';
-import StatusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetConflicts',
components: {
GlSkeletonLoader,
- StatusIcon,
GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
@@ -86,29 +86,23 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :show-disabled-button="true" status="warning" />
-
- <div v-if="isLoading" class="gl-ml-4 gl-w-full mr-conflict-loader">
+ <state-container status="warning" :is-loading="isLoading">
+ <template #loading>
<gl-skeleton-loader :width="334" :height="30">
<rect x="0" y="7" width="150" height="16" rx="4" />
<rect x="158" y="7" width="84" height="16" rx="4" />
<rect x="250" y="7" width="84" height="16" rx="4" />
</gl-skeleton-loader>
- </div>
- <div v-else class="media-body space-children gl-display-flex gl-align-items-center">
- <span
- v-if="shouldBeRebased"
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="bold"
- >
+ </template>
+ <template v-if="!isLoading">
+ <span v-if="shouldBeRebased" class="bold gl-ml-0! gl-text-body!">
{{
s__(`mrWidget|Merge blocked: fast-forward merge is not possible.
To merge this request, first rebase locally.`)
}}
</span>
<template v-else>
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="bold gl-ml-0! gl-text-body! gl-flex-grow-1 gl-w-full gl-md-w-auto gl-mr-2">
{{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }}
<span v-if="!canMerge">
{{
@@ -118,23 +112,30 @@ export default {
}}
</span>
</span>
- <gl-button
- v-if="showResolveButton"
- :href="mr.conflictResolutionPath"
- :size="glFeatures.restructuredMrWidget ? 'small' : 'medium'"
- data-testid="resolve-conflicts-button"
- >
- {{ s__('mrWidget|Resolve conflicts') }}
- </gl-button>
- <gl-button
- v-if="canMerge"
- :size="glFeatures.restructuredMrWidget ? 'small' : 'medium'"
- data-testid="merge-locally-button"
- class="js-check-out-modal-trigger"
- >
- {{ s__('mrWidget|Resolve locally') }}
- </gl-button>
</template>
- </div>
- </div>
+ </template>
+ <template v-if="!isLoading && !shouldBeRebased" #actions>
+ <gl-button
+ v-if="canMerge"
+ size="small"
+ variant="confirm"
+ category="secondary"
+ data-testid="merge-locally-button"
+ class="js-check-out-modal-trigger gl-align-self-start"
+ :class="{ 'gl-mr-2': showResolveButton }"
+ >
+ {{ s__('mrWidget|Resolve locally') }}
+ </gl-button>
+ <gl-button
+ v-if="showResolveButton"
+ :href="mr.conflictResolutionPath"
+ size="small"
+ variant="confirm"
+ class="gl-mb-2 gl-md-mb-0 gl-align-self-start"
+ data-testid="resolve-conflicts-button"
+ >
+ {{ s__('mrWidget|Resolve conflicts') }}
+ </gl-button>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
index 42e9261b82c..18103ac4a0e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
@@ -30,7 +30,7 @@ export default {
computed: {
mergeError() {
- const mergeError = this.mr.mergeError ? stripHtml(this.mr.mergeError, ' ').trim() : '';
+ const mergeError = this.prepareMergeError(this.mr.mergeError);
return sprintf(
s__('mrWidget|%{mergeError}.'),
@@ -76,6 +76,13 @@ export default {
this.refresh();
}
},
+ prepareMergeError(mergeError) {
+ return mergeError
+ ? stripHtml(mergeError, ' ')
+ .replace(/(\.$|\s+)/g, ' ')
+ .trim()
+ : '';
+ },
},
};
</script>
@@ -89,7 +96,9 @@ export default {
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- <span v-if="mr.mergeError" class="has-error-message"> {{ mergeError }} </span>
+ <span v-if="mr.mergeError" class="has-error-message" data-testid="merge-error">
+ {{ mergeError }}
+ </span>
<span v-else> {{ s__('mrWidget|Merge failed.') }} </span>
<span :class="{ 'has-custom-error': mr.mergeError }"> {{ timerText }} </span>
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index bf036f562ed..4416123cd51 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -1,15 +1,13 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLoadingIcon, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import api from '~/api';
import createFlash from '~/flash';
import { s__, __ } from '~/locale';
import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/constants';
import modalEventHub from '~/projects/commit/event_hub';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../../event_hub';
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetMerged',
@@ -19,11 +17,8 @@ export default {
components: {
MrWidgetAuthorTime,
GlIcon,
- ClipboardButton,
- GlLoadingIcon,
- GlButton,
+ StateContainer,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -78,6 +73,53 @@ export default {
cherryPickLabel() {
return s__('mrWidget|Cherry-pick');
},
+ actions() {
+ const actions = [];
+
+ if (this.mr.canRevertInCurrentMR) {
+ actions.push({
+ text: this.revertLabel,
+ tooltipText: this.revertTitle,
+ dataQaSelector: 'revert_button',
+ onClick: () => this.openRevertModal(),
+ });
+ } else if (this.mr.revertInForkPath) {
+ actions.push({
+ text: this.revertLabel,
+ tooltipText: this.revertTitle,
+ href: this.mr.revertInForkPath,
+ dataQaSelector: 'revert_button',
+ dataMethod: 'post',
+ });
+ }
+
+ if (this.mr.canCherryPickInCurrentMR) {
+ actions.push({
+ text: this.cherryPickLabel,
+ tooltipText: this.cherryPickTitle,
+ dataQaSelector: 'cherry_pick_button',
+ onClick: () => this.openCherryPickModal(),
+ });
+ } else if (this.mr.cherryPickInForkPath) {
+ actions.push({
+ text: this.cherryPickLabel,
+ tooltipText: this.cherryPickTitle,
+ href: this.mr.cherryPickInForkPath,
+ dataQaSelector: 'cherry_pick_button',
+ dataMethod: 'post',
+ });
+ }
+
+ if (this.shouldShowRemoveSourceBranch) {
+ actions.push({
+ text: s__('mrWidget|Delete source branch'),
+ class: 'js-remove-branch-button',
+ onClick: () => this.removeSourceBranch(),
+ });
+ }
+
+ return actions;
+ },
},
mounted() {
document.dispatchEvent(new CustomEvent('merged:UpdateActions'));
@@ -121,103 +163,15 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <gl-icon name="merge" :size="24" class="gl-text-blue-500 gl-mr-3 gl-mt-1" />
- <div class="media-body">
- <div class="space-children">
- <mr-widget-author-time
- :action-text="s__('mrWidget|Merged by')"
- :author="mr.metrics.mergedBy"
- :date-title="mr.metrics.mergedAt"
- :date-readable="mr.metrics.readableMergedAt"
- />
- <gl-button
- v-if="mr.canRevertInCurrentMR"
- v-gl-tooltip.hover
- :title="revertTitle"
- size="small"
- category="secondary"
- data-qa-selector="revert_button"
- @click="openRevertModal"
- >
- {{ revertLabel }}
- </gl-button>
- <gl-button
- v-else-if="mr.revertInForkPath"
- v-gl-tooltip.hover
- :href="mr.revertInForkPath"
- :title="revertTitle"
- size="small"
- category="secondary"
- data-method="post"
- >
- {{ revertLabel }}
- </gl-button>
- <gl-button
- v-if="mr.canCherryPickInCurrentMR"
- v-gl-tooltip.hover
- :title="cherryPickTitle"
- size="small"
- data-qa-selector="cherry_pick_button"
- @click="openCherryPickModal"
- >
- {{ cherryPickLabel }}
- </gl-button>
- <gl-button
- v-else-if="mr.cherryPickInForkPath"
- v-gl-tooltip.hover
- :href="mr.cherryPickInForkPath"
- :title="cherryPickTitle"
- size="small"
- data-method="post"
- >
- {{ cherryPickLabel }}
- </gl-button>
- <gl-button
- v-if="shouldShowRemoveSourceBranch"
- :disabled="isMakingRequest"
- size="small"
- class="js-remove-branch-button"
- @click="removeSourceBranch"
- >
- {{ s__('mrWidget|Delete source branch') }}
- </gl-button>
- </div>
- <section
- v-if="!glFeatures.restructuredMrWidget"
- class="mr-info-list"
- data-qa-selector="merged_status_content"
- >
- <p>
- {{ s__('mrWidget|The changes were merged into') }}
- <span class="label-branch">
- <a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
- </span>
- <template v-if="mr.mergeCommitSha">
- with
- <a
- :href="mr.mergeCommitPath"
- class="commit-sha js-mr-merged-commit-sha"
- v-text="mr.shortMergeCommitSha"
- >
- </a>
- <clipboard-button
- :title="__('Copy commit SHA')"
- :text="mr.mergeCommitSha"
- css-class="js-mr-merged-copy-sha"
- category="tertiary"
- size="small"
- />
- </template>
- </p>
- <p v-if="mr.sourceBranchRemoved">
- {{ s__('mrWidget|The source branch has been deleted') }}
- </p>
- <p v-if="shouldShowSourceBranchRemoving">
- <gl-loading-icon size="sm" :inline="true" />
- <span> {{ s__('mrWidget|The source branch is being deleted') }} </span>
- </p>
- </section>
- </div>
- </div>
+ <state-container :actions="actions">
+ <template #icon>
+ <gl-icon name="merge" :size="24" class="gl-text-blue-500 gl-mr-3 gl-mt-1" />
+ </template>
+ <mr-widget-author-time
+ :action-text="s__('mrWidget|Merged by')"
+ :author="mr.metrics.mergedBy"
+ :date-title="mr.metrics.mergedAt"
+ :date-readable="mr.metrics.readableMergedAt"
+ />
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
index b86ab69af3f..c7574a41bb8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
@@ -1,6 +1,5 @@
<script>
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import simplePoll from '~/lib/utils/simple_poll';
import MergeRequest from '~/merge_request';
import eventHub from '../../event_hub';
@@ -15,7 +14,6 @@ export default {
components: {
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -90,14 +88,6 @@ export default {
{{ mergeStatus.message }}
<gl-emoji :data-name="mergeStatus.emoji" />
</h4>
- <section v-if="!glFeatures.restructuredMrWidget" class="mr-info-list">
- <p>
- {{ s__('mrWidget|Merges changes into') }}
- <span class="label-branch">
- <a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
- </span>
- </p>
- </section>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
index cadbd9c28a9..659d12d1160 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
@@ -74,13 +74,7 @@ export default {
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span
- :class="{
- 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget,
- }"
- class="bold js-branch-text"
- data-testid="widget-content"
- >
+ <span class="gl-ml-0! gl-text-body! bold js-branch-text" data-testid="widget-content">
<gl-sprintf :message="warning">
<template #code="{ content }">
<code>{{ content }}</code>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
index 34c5a2ff2c8..e99ee59b877 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
@@ -14,7 +14,7 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
{{
s__(
`mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue.`,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index 59767eb2e6e..6c5fc916799 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -8,7 +8,7 @@ import simplePoll from '~/lib/utils/simple_poll';
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import rebaseQuery from '../../queries/states/rebase.query.graphql';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'MRWidgetRebase',
@@ -25,9 +25,9 @@ export default {
},
},
components: {
- statusIcon,
GlSkeletonLoader,
GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
props: {
@@ -51,9 +51,6 @@ export default {
isLoading() {
return this.glFeatures.mergeRequestWidgetGraphql && this.$apollo.queries.state.loading;
},
- showRebaseWithoutCi() {
- return this.glFeatures?.rebaseWithoutCiUi;
- },
rebaseInProgress() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.rebaseInProgress;
@@ -76,6 +73,10 @@ export default {
return this.mr.targetBranch;
},
status() {
+ if (this.isLoading) {
+ return undefined;
+ }
+
if (this.rebaseInProgress || this.isMakingRequest) {
return 'loading';
}
@@ -148,92 +149,70 @@ export default {
};
</script>
<template>
- <div class="mr-widget-body media">
- <div v-if="isLoading" class="gl-w-full mr-conflict-loader">
+ <state-container :status="status" :is-loading="isLoading">
+ <template #loading>
<gl-skeleton-loader :width="334" :height="30">
<rect x="0" y="3" width="24" height="24" rx="4" />
<rect x="32" y="5" width="302" height="20" rx="4" />
</gl-skeleton-loader>
- </div>
- <template v-else>
- <status-icon :status="status" :show-disabled-button="showDisabledButton" />
-
- <div class="rebase-state-find-class-convention media media-body space-children">
+ </template>
+ <template v-if="!isLoading">
+ <span
+ v-if="rebaseInProgress || isMakingRequest"
+ class="gl-ml-0! gl-text-body! gl-font-weight-bold"
+ data-testid="rebase-message"
+ >{{ __('Rebase in progress') }}</span
+ >
+ <span
+ v-if="!rebaseInProgress && !canPushToSourceBranch"
+ class="gl-text-body! gl-font-weight-bold gl-ml-0!"
+ data-testid="rebase-message"
+ >{{ fastForwardMergeText }}</span
+ >
+ <div
+ v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest"
+ class="accept-merge-holder clearfix js-toggle-container media gl-md-display-flex gl-flex-wrap gl-flex-grow-1"
+ >
<span
- v-if="rebaseInProgress || isMakingRequest"
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold"
+ v-if="!rebasingError"
+ class="gl-font-weight-bold gl-w-100 gl-md-w-auto gl-flex-grow-1 gl-ml-0! gl-text-body! gl-md-mr-3"
data-testid="rebase-message"
- >{{ __('Rebase in progress') }}</span
+ data-qa-selector="no_fast_forward_message_content"
+ >{{
+ __('Merge blocked: the source branch must be rebased onto the target branch.')
+ }}</span
>
<span
- v-if="!rebaseInProgress && !canPushToSourceBranch"
- :class="{ 'gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold gl-ml-0!"
+ v-else
+ class="gl-font-weight-bold danger gl-w-100 gl-md-w-auto gl-flex-grow-1 gl-md-mr-3"
data-testid="rebase-message"
- >{{ fastForwardMergeText }}</span
- >
- <div
- v-if="!rebaseInProgress && canPushToSourceBranch && !isMakingRequest"
- class="accept-merge-holder clearfix js-toggle-container accept-action media space-children gl-align-items-center"
+ >{{ rebasingError }}</span
>
- <gl-button
- v-if="!glFeatures.restructuredMrWidget"
- :loading="isMakingRequest"
- variant="confirm"
- data-qa-selector="mr_rebase_button"
- data-testid="standard-rebase-button"
- @click="rebase"
- >
- {{ __('Rebase') }}
- </gl-button>
- <gl-button
- v-if="!glFeatures.restructuredMrWidget && showRebaseWithoutCi"
- :loading="isMakingRequest"
- variant="confirm"
- category="secondary"
- data-testid="rebase-without-ci-button"
- @click="rebaseWithoutCi"
- >
- {{ __('Rebase without pipeline') }}
- </gl-button>
- <span
- v-if="!rebasingError"
- :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }"
- class="gl-font-weight-bold"
- data-testid="rebase-message"
- data-qa-selector="no_fast_forward_message_content"
- >{{
- __('Merge blocked: the source branch must be rebased onto the target branch.')
- }}</span
- >
- <span v-else class="gl-font-weight-bold danger" data-testid="rebase-message">{{
- rebasingError
- }}</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>
- <gl-button
- v-if="glFeatures.restructuredMrWidget && showRebaseWithoutCi"
- :loading="isMakingRequest"
- variant="confirm"
- size="small"
- category="secondary"
- data-testid="rebase-without-ci-button"
- @click="rebaseWithoutCi"
- >
- {{ __('Rebase without pipeline') }}
- </gl-button>
- </div>
</div>
</template>
- </div>
+ <template v-if="!isLoading" #actions>
+ <gl-button
+ :loading="isMakingRequest"
+ variant="confirm"
+ size="small"
+ category="secondary"
+ data-testid="rebase-without-ci-button"
+ class="gl-align-self-start gl-mr-2"
+ @click="rebaseWithoutCi"
+ >
+ {{ __('Rebase without pipeline') }}
+ </gl-button>
+ <gl-button
+ :loading="isMakingRequest"
+ variant="confirm"
+ size="small"
+ data-qa-selector="mr_rebase_button"
+ data-testid="standard-rebase-button"
+ class="gl-mb-2 gl-md-mb-0 gl-align-self-start"
+ @click="rebase"
+ >
+ {{ __('Rebase') }}
+ </gl-button>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
index d204befef58..d507e5f232b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
@@ -1,7 +1,6 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { s__ } from '~/locale';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -12,7 +11,6 @@ export default {
GlSprintf,
statusIcon,
},
- mixins: [glFeatureFlagMixin()],
computed: {
troubleshootingDocsPath() {
return helpPagePath('ci/troubleshooting', { anchor: 'merge-request-status-messages' });
@@ -30,7 +28,7 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span :class="{ 'gl-ml-0! gl-text-body!': glFeatures.restructuredMrWidget }" class="bold">
+ <span class="gl-ml-0! gl-text-body! bold">
<gl-sprintf :message="$options.i18n.failedMessage">
<template #link="{ content }">
<gl-link :href="troubleshootingDocsPath" target="_blank">
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 cf482410bef..d2c85b14999 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
@@ -31,12 +31,10 @@ import {
import eventHub from '../../event_hub';
import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_variables';
import MergeRequestStore from '../../stores/mr_widget_store';
-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 CommitMessageDropdown from './commit_message_dropdown.vue';
-import CommitsHeader from './commits_header.vue';
import SquashBeforeMerge from './squash_before_merge.vue';
import MergeFailedPipelineConfirmationDialog from './merge_failed_pipeline_confirmation_dialog.vue';
@@ -96,9 +94,7 @@ export default {
},
},
components: {
- statusIcon,
SquashBeforeMerge,
- CommitsHeader,
CommitEdit,
CommitMessageDropdown,
GlIcon,
@@ -320,34 +316,27 @@ export default {
showDangerMessageForMergeTrain() {
return this.preferredAutoMergeStrategy === MT_MERGE_STRATEGY && this.isPipelineFailed;
},
- restructuredWidgetShowMergeButtons() {
- if (this.glFeatures.restructuredMrWidget) {
- return (
- (this.isMergeAllowed || this.isAutoMergeAvailable) &&
- this.state.userPermissions.canMerge &&
- !this.mr.mergeOngoing &&
- !this.mr.autoMergeEnabled
- );
- }
-
- return true;
+ shouldShowMergeControls() {
+ return (
+ (this.isMergeAllowed || this.isAutoMergeAvailable) &&
+ (this.stateData.userPermissions?.canMerge || this.mr.canMerge) &&
+ !this.mr.mergeOngoing &&
+ !this.mr.autoMergeEnabled
+ );
},
sourceBranchDeletedText() {
- if (this.glFeatures.restructuredMrWidget) {
- if (this.removeSourceBranch) {
- return this.mr.state === 'merged'
- ? __('Deleted the source branch.')
- : __('Source branch will be deleted.');
- }
-
+ if (this.removeSourceBranch) {
return this.mr.state === 'merged'
- ? __('Did not delete the source branch.')
- : __('Source branch will not be deleted.');
+ ? __('Deleted the source branch.')
+ : __('Source branch will be deleted.');
}
- return this.removeSourceBranch
- ? __('Deletes the source branch.')
- : __('Does not delete the source branch.');
+ return this.mr.state === 'merged'
+ ? __('Did not delete the source branch.')
+ : __('Source branch will not be deleted.');
+ },
+ showMergeDetailsHeader() {
+ return ['readyToMerge'].indexOf(this.mr.state) >= 0;
},
},
mounted() {
@@ -525,10 +514,7 @@ export default {
<template>
<div
data-testid="ready_to_merge_state"
- :class="{
- '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,
- }"
+ class="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"
>
<div v-if="loading" class="mr-widget-body">
<div class="gl-w-full mr-ready-to-merge-loader">
@@ -541,16 +527,10 @@ export default {
</div>
</div>
<template v-else>
- <div
- class="mr-widget-body media"
- :class="{
- 'mr-widget-body-line-height-1': glFeatures.restructuredMrWidget,
- }"
- >
- <status-icon v-if="!glFeatures.restructuredMrWidget" :status="iconClass" />
+ <div class="mr-widget-body mr-widget-body-ready-merge media mr-widget-body-line-height-1">
<div class="media-body">
<div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap">
- <gl-button-group v-if="restructuredWidgetShowMergeButtons" class="gl-align-self-start">
+ <gl-button-group v-if="shouldShowMergeControls" class="gl-align-self-start">
<gl-button
size="medium"
category="primary"
@@ -603,19 +583,14 @@ export default {
<merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
<div
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 gl-w-full gl-order-n1 gl-mb-5"
>
<gl-form-checkbox
v-if="canRemoveSourceBranch"
id="remove-source-branch-input"
v-model="removeSourceBranch"
:disabled="isRemoveSourceBranchButtonDisabled"
- :class="{
- 'gl-mx-3': !glFeatures.restructuredMrWidget,
- 'gl-mr-5': glFeatures.restructuredMrWidget,
- }"
- class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center"
+ class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5"
>
{{ __('Delete source branch') }}
</gl-form-checkbox>
@@ -626,16 +601,11 @@ export default {
v-model="squashBeforeMerge"
:help-path="mr.squashBeforeMergeHelpPath"
:is-disabled="isSquashReadOnly"
- :class="{
- 'gl-mx-3': !glFeatures.restructuredMrWidget,
- 'gl-mr-5': glFeatures.restructuredMrWidget,
- }"
+ class="gl-mr-5"
/>
<gl-form-checkbox
- v-if="
- glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)
- "
+ v-if="shouldShowSquashEdit || shouldShowMergeEdit"
v-model="editCommitMessage"
data-testid="widget_edit_commit_message"
class="gl-display-flex gl-align-items-center"
@@ -644,198 +614,113 @@ export default {
</gl-form-checkbox>
</div>
<div
- v-else-if="!glFeatures.restructuredMrWidget"
- class="bold js-resolve-mr-widget-items-message gl-ml-3"
+ v-if="editCommitMessage"
+ class="gl-w-full gl-order-n1"
+ data-testid="edit_commit_message"
>
- <div
- v-if="hasPipelineMustSucceedConflict"
- class="gl-display-flex gl-align-items-center"
- data-testid="pipeline-succeed-conflict"
- >
- <gl-sprintf :message="pipelineMustSucceedConflictText" />
- <gl-link
- :href="mr.pipelineMustSucceedDocsPath"
- target="_blank"
- class="gl-display-flex gl-ml-2"
+ <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4">
+ <commit-edit
+ v-if="shouldShowSquashEdit"
+ :value="squashCommitMessage"
+ :label="__('Squash commit message')"
+ input-id="squash-message-edit"
+ class="gl-m-0! gl-p-0!"
+ @input="setSquashCommitMessage"
>
- <gl-icon name="question" />
- </gl-link>
- </div>
- <gl-sprintf v-else :message="mergeDisabledText" />
+ <template #header>
+ <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ </template>
+ </commit-edit>
+ <commit-edit
+ v-if="shouldShowMergeEdit"
+ :value="commitMessage"
+ :label="__('Merge commit message')"
+ input-id="merge-message-edit"
+ class="gl-m-0! gl-p-0!"
+ @input="setCommitMessage"
+ />
+ <li class="gl-m-0! gl-p-0!">
+ <p class="form-text text-muted">
+ <gl-sprintf :message="commitTemplateHintText">
+ <template #link="{ content }">
+ <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </li>
+ </ul>
</div>
- <template v-if="glFeatures.restructuredMrWidget">
- <div
- v-if="editCommitMessage"
- class="gl-w-full gl-order-n1"
- data-testid="edit_commit_message"
- >
- <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"
- :value="squashCommitMessage"
- :label="__('Squash commit message')"
- input-id="squash-message-edit"
- class="gl-m-0! gl-p-0!"
- @input="setSquashCommitMessage"
+ <div
+ v-if="!shouldShowMergeControls"
+ class="gl-w-full gl-order-n1 mr-widget-merge-details"
+ data-qa-selector="merged_status_content"
+ >
+ <p v-if="showMergeDetailsHeader" class="gl-mb-3 gl-text-gray-900">
+ {{ __('Merge details') }}
+ </p>
+ <ul class="gl-pl-4 gl-mb-0 gl-ml-3 gl-text-gray-600">
+ <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal">
+ <gl-sprintf
+ :message="s__('mrWidget|The source branch is %{link} the target branch')"
>
- <template #header>
- <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
+ <template #link>
+ <gl-link :href="mr.targetBranchPath">{{
+ n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
+ }}</gl-link>
</template>
- </commit-edit>
- <commit-edit
- v-if="shouldShowMergeEdit"
- :value="commitMessage"
- :label="__('Merge commit message')"
- input-id="merge-message-edit"
- class="gl-m-0! gl-p-0!"
- @input="setCommitMessage"
+ </gl-sprintf>
+ </li>
+ <li class="gl-line-height-normal">
+ <added-commit-message
+ :state="mr.state"
+ :merge-commit-sha="mr.shortMergeCommitSha"
+ :is-squash-enabled="squashBeforeMerge"
+ :is-fast-forward-enabled="!shouldShowMergeEdit"
+ :commits-count="commitsCount"
+ :target-branch="stateData.targetBranch"
/>
- <li class="gl-m-0! gl-p-0!">
- <p class="form-text text-muted">
- <gl-sprintf :message="commitTemplateHintText">
- <template #link="{ content }">
- <gl-link
- :href="commitTemplateHelpPage"
- class="inline-link"
- target="_blank"
- >
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </li>
- </ul>
- </div>
- <div
- v-if="!restructuredWidgetShowMergeButtons"
- class="gl-w-full gl-order-n1 gl-text-gray-500"
- data-qa-selector="merged_status_content"
- >
- <strong v-if="mr.state !== 'closed'">
- {{ __('Merge details') }}
- </strong>
- <ul class="gl-pl-4 gl-m-0">
- <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal">
- <gl-sprintf
- :message="s__('mrWidget|The source branch is %{link} the target branch')"
- >
- <template #link>
- <gl-link :href="mr.targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </li>
- <li class="gl-line-height-normal">
- <added-commit-message
- :state="mr.state"
- :merge-commit-sha="mr.shortMergeCommitSha"
- :is-squash-enabled="squashBeforeMerge"
- :is-fast-forward-enabled="!shouldShowMergeEdit"
- :commits-count="commitsCount"
- :target-branch="stateData.targetBranch"
- />
- </li>
- <li v-if="mr.state !== 'closed'" class="gl-line-height-normal">
- {{ sourceBranchDeletedText }}
- </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;
+ </li>
+ <li v-if="mr.state !== 'closed'" class="gl-line-height-normal">
+ {{ sourceBranchDeletedText }}
+ </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"
- :diverged-commits-count="mr.divergedCommitsCount"
- :target-branch-path="mr.targetBranchPath"
class="mr-ready-merge-related-links gl-display-inline"
/>
- </template>
- </div>
- </template>
- </div>
- <div
- v-if="showDangerMessageForMergeTrain && !glFeatures.restructuredMrWidget"
- class="gl-mt-5 gl-text-gray-500"
- data-testid="failed-pipeline-merge-train-text"
- >
- {{ __('The latest pipeline for this merge request did not complete successfully.') }}
+ </li>
+ </ul>
+ </div>
+ <div
+ v-else
+ :class="{ 'gl-mb-5': shouldShowMergeControls }"
+ 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"
+ :diverged-commits-count="mr.divergedCommitsCount"
+ :target-branch-path="mr.targetBranchPath"
+ class="mr-ready-merge-related-links gl-display-inline"
+ />
+ </template>
+ </div>
</div>
</div>
</div>
- <template v-if="shouldShowMergeControls && !glFeatures.restructuredMrWidget">
- <div v-if="!shouldShowMergeEdit" class="mr-fast-forward-message">
- {{ __('Fast-forward merge without a merge commit') }}
- </div>
- <commits-header
- v-if="!glFeatures.restructuredMrWidget && (shouldShowSquashEdit || shouldShowMergeEdit)"
- :is-squash-enabled="squashBeforeMerge"
- :commits-count="commitsCount"
- :target-branch="stateData.targetBranch"
- :is-fast-forward-enabled="!shouldShowMergeEdit"
- :class="{ 'border-bottom': stateData.mergeError }"
- >
- <ul class="border-top content-list commits-list flex-list">
- <commit-edit
- v-if="shouldShowSquashEdit"
- :value="squashCommitMessage"
- :label="__('Squash commit message')"
- input-id="squash-message-edit"
- squash
- @input="setSquashCommitMessage"
- >
- <template #header>
- <commit-message-dropdown :commits="commits" @input="setSquashCommitMessage" />
- </template>
- </commit-edit>
- <commit-edit
- v-if="shouldShowMergeEdit"
- :value="commitMessage"
- :label="__('Merge commit message')"
- input-id="merge-message-edit"
- @input="setCommitMessage"
- />
- <li>
- <p class="form-text text-muted">
- <gl-sprintf :message="commitTemplateHintText">
- <template #link="{ content }">
- <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </li>
- </ul>
- </commits-header>
- </template>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
index b1fbe150fcf..d149f5208fc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
@@ -1,19 +1,17 @@
<script>
import { GlButton } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { I18N_SHA_MISMATCH } from '../../i18n';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'ShaMismatch',
components: {
- statusIcon,
GlButton,
+ StateContainer,
},
i18n: {
I18N_SHA_MISMATCH,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -24,25 +22,24 @@ export default {
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :show-disabled-button="false" status="warning" />
- <div class="media-body">
- <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 }}
- </span>
+ <state-container status="warning">
+ <span
+ class="gl-font-weight-bold gl-md-mr-3 gl-flex-grow-1 gl-ml-0! gl-text-body!"
+ data-qa-selector="head_mismatch_content"
+ >
+ {{ $options.i18n.I18N_SHA_MISMATCH.warningMessage }}
+ </span>
+ <template #actions>
<gl-button
- class="gl-ml-3"
data-testid="action-button"
size="small"
category="primary"
variant="confirm"
+ class="gl-align-self-start"
:href="mr.mergeRequestDiffsPath"
- >{{ $options.i18n.I18N_SHA_MISMATCH.actionButtonLabel }}</gl-button
>
- </div>
- </div>
+ {{ $options.i18n.I18N_SHA_MISMATCH.actionButtonLabel }}
+ </gl-button>
+ </template>
+ </state-container>
</template>
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 c6227c4394d..1413a46b4b9 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
@@ -1,6 +1,5 @@
<script>
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 {
@@ -12,7 +11,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [glFeatureFlagsMixin()],
i18n: {
...SQUASH_BEFORE_MERGE,
},
@@ -36,9 +34,6 @@ export default {
tooltipTitle() {
return this.isDisabled ? this.$options.i18n.tooltipTitle : null;
},
- helpIconName() {
- return this.glFeatures.restructuredMrWidget ? 'question-o' : 'question';
- },
},
};
</script>
@@ -62,10 +57,10 @@ export default {
v-gl-tooltip
:href="helpPath"
:title="$options.i18n.helpLabel"
- :class="{ 'gl-text-blue-600': glFeatures.restructuredMrWidget }"
+ class="gl-text-blue-600"
target="_blank"
>
- <gl-icon :name="helpIconName" />
+ <gl-icon name="question-o" />
<span class="sr-only">
{{ $options.i18n.helpLabel }}
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
index 25ba4bf12af..035d62eaa59 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
@@ -1,16 +1,14 @@
<script>
import { GlButton } from '@gitlab/ui';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import notesEventHub from '~/notes/event_hub';
-import statusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'UnresolvedDiscussions',
components: {
- statusIcon,
GlButton,
+ StateContainer,
},
- mixins: [glFeatureFlagMixin()],
props: {
mr: {
type: Object,
@@ -26,38 +24,33 @@ export default {
</script>
<template>
- <div class="mr-widget-body media gl-flex-wrap">
- <status-icon show-disabled-button status="warning" />
- <div class="media-body">
- <span
- :class="{
- '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>
+ <state-container status="warning">
+ <span
+ class="gl-ml-3 gl-font-weight-bold gl-w-100 gl-flex-grow-1 gl-md-mr-3 gl-ml-0! gl-text-body!"
+ >
+ {{ s__('mrWidget|Merge blocked: all threads must be resolved.') }}
+ </span>
+ <template #actions>
<gl-button
- data-testid="jump-to-first"
- class="gl-ml-3"
+ v-if="mr.createIssueToResolveDiscussionsPath"
+ :href="mr.createIssueToResolveDiscussionsPath"
+ class="js-create-issue gl-align-self-start gl-vertical-align-top gl-mr-2"
size="small"
- :icon="glFeatures.restructuredMrWidget ? undefined : 'comment-next'"
- :variant="glFeatures.restructuredMrWidget ? 'confirm' : 'default'"
- :category="glFeatures.restructuredMrWidget ? 'secondary' : 'primary'"
- @click="jumpToFirstUnresolvedDiscussion"
+ variant="confirm"
+ category="secondary"
>
- {{ s__('mrWidget|Jump to first unresolved thread') }}
+ {{ s__('mrWidget|Create issue to resolve all threads') }}
</gl-button>
<gl-button
- v-if="mr.createIssueToResolveDiscussionsPath"
- :href="mr.createIssueToResolveDiscussionsPath"
- class="js-create-issue gl-ml-3"
+ data-testid="jump-to-first"
+ class="gl-mb-2 gl-md-mb-0 gl-align-self-start gl-vertical-align-top"
size="small"
- :icon="glFeatures.restructuredMrWidget ? undefined : 'issue-new'"
+ variant="confirm"
+ category="primary"
+ @click="jumpToFirstUnresolvedDiscussion"
>
- {{ s__('mrWidget|Create issue to resolve all threads') }}
+ {{ s__('mrWidget|Jump to first unresolved thread') }}
</gl-button>
- </div>
- </div>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index 5bd7745d704..cf7f83c014a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -12,13 +12,13 @@ import mergeRequestQueryVariablesMixin from '../../mixins/merge_request_query_va
import getStateQuery from '../../queries/get_state.query.graphql';
import draftQuery from '../../queries/states/draft.query.graphql';
import removeDraftMutation from '../../queries/toggle_draft.mutation.graphql';
-import StatusIcon from '../mr_widget_status_icon.vue';
+import StateContainer from '../state_container.vue';
export default {
name: 'WorkInProgress',
components: {
- StatusIcon,
GlButton,
+ StateContainer,
},
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
apollo: {
@@ -163,29 +163,22 @@ export default {
</script>
<template>
- <div class="mr-widget-body media">
- <status-icon :show-disabled-button="canUpdate" status="warning" />
- <div class="media-body">
- <div class="float-left">
- <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.")
- }}
- </span>
- </div>
+ <state-container status="warning">
+ <span class="gl-font-weight-bold gl-ml-0! gl-text-body! gl-flex-grow-1">
+ {{ __("Merge blocked: merge request must be marked as ready. It's still marked as draft.") }}
+ </span>
+ <template #actions>
<gl-button
v-if="canUpdate"
size="small"
:disabled="isMakingRequest"
:loading="isMakingRequest"
- class="js-remove-draft gl-ml-3"
+ variant="confirm"
+ class="js-remove-draft gl-md-ml-3 gl-align-self-start"
@click="handleRemoveDraft"
>
{{ s__('mrWidget|Mark as ready') }}
</gl-button>
- </div>
- </div>
+ </template>
+ </state-container>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
new file mode 100644
index 00000000000..f1c1bde256f
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
@@ -0,0 +1,27 @@
+<script>
+export default {
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ widgets() {
+ return [].filter((w) => w);
+ },
+ },
+};
+</script>
+
+<template>
+ <section role="region" :aria-label="__('Merge request reports')" data-testid="mr-widget-app">
+ <component
+ :is="widget"
+ v-for="(widget, index) in widgets"
+ :key="widget.name || index"
+ :mr="mr"
+ :class="{ 'mr-widget-border-top': index === 0 }"
+ />
+ </section>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
new file mode 100644
index 00000000000..9c8819327e6
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
@@ -0,0 +1,158 @@
+<script>
+import * as Sentry from '@sentry/browser';
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import Poll from '~/lib/utils/poll';
+import StatusIcon from '../extensions/status_icon.vue';
+import { EXTENSION_ICON_NAMES } from '../../constants';
+
+const FETCH_TYPE_COLLAPSED = 'collapsed';
+
+export default {
+ components: {
+ StatusIcon,
+ },
+ props: {
+ /**
+ * @param {value.collapsed} Object
+ * @param {value.extended} Object
+ */
+ value: {
+ type: Object,
+ required: true,
+ },
+ loadingText: {
+ type: String,
+ required: false,
+ default: __('Loading'),
+ },
+ errorText: {
+ type: String,
+ required: false,
+ default: __('Failed to load'),
+ },
+ fetchCollapsedData: {
+ type: Function,
+ required: true,
+ },
+ fetchExtendedData: {
+ type: Function,
+ required: false,
+ default: undefined,
+ },
+ // If the summary slot is not used, this value will be used as a fallback.
+ summary: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ // If the content slot is not used, this value will be used as a fallback.
+ content: {
+ type: Object,
+ required: false,
+ default: undefined,
+ },
+ multiPolling: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ statusIconName: {
+ type: String,
+ default: 'neutral',
+ required: false,
+ validator: (value) => Object.keys(EXTENSION_ICON_NAMES).indexOf(value) > -1,
+ },
+ widgetName: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isLoading: false,
+ error: null,
+ };
+ },
+ watch: {
+ isLoading(newValue) {
+ this.$emit('is-loading', newValue);
+ },
+ },
+ async mounted() {
+ this.isLoading = true;
+
+ try {
+ await this.fetch(this.fetchCollapsedData, FETCH_TYPE_COLLAPSED);
+ } catch {
+ this.error = this.errorText;
+ }
+
+ this.isLoading = false;
+ },
+ methods: {
+ fetch(handler, dataType) {
+ const requests = this.multiPolling ? handler() : [handler];
+
+ const promises = requests.map((request) => {
+ return new Promise((resolve, reject) => {
+ const poll = new Poll({
+ resource: {
+ fetchData: () => request(),
+ },
+ method: 'fetchData',
+ successCallback: (response) => {
+ const headers = normalizeHeaders(response.headers);
+
+ if (headers['POLL-INTERVAL']) {
+ return;
+ }
+
+ resolve(response.data);
+ },
+ errorCallback: (e) => {
+ Sentry.captureException(e);
+ reject(e);
+ },
+ });
+
+ poll.makeRequest();
+ });
+ });
+
+ return Promise.all(promises).then((data) => {
+ this.$emit('input', { ...this.value, [dataType]: this.multiPolling ? data : data[0] });
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <section class="media-section" data-testid="widget-extension">
+ <div class="media gl-p-5">
+ <status-icon
+ :level="1"
+ :name="widgetName"
+ :is-loading="isLoading"
+ :icon-name="statusIconName"
+ />
+ <div
+ class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center"
+ data-testid="widget-extension-top-level"
+ >
+ <div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary">
+ <slot name="summary">{{ isLoading ? loadingText : summary }}</slot>
+ </div>
+ <!-- actions will go here -->
+ <!-- toggle button will go here -->
+ </div>
+ </div>
+ <div
+ class="mr-widget-grouped-section gl-relative"
+ data-testid="widget-extension-collapsed-section"
+ >
+ <slot name="content">{{ content }}</slot>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
index 22e907f7e48..0fb5e13ad82 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/accessibility/index.js
@@ -6,7 +6,6 @@ import { EXTENSION_ICONS } from '../../constants';
export default {
name: 'WidgetAccessibility',
enablePolling: true,
- telemetry: false,
i18n: {
loading: s__('Reports|Accessibility scanning results are being parsed'),
error: s__('Reports|Accessibility scanning failed loading results'),
@@ -76,9 +75,9 @@ export default {
return sprintf(s__('AccessibilityReport|Message: %{message}'), { message });
},
prepareReports() {
- const { new_errors, existing_errors, resolved_errors } = this.collapsedData;
+ const { collapsedData } = this;
- const newErrors = new_errors.map((error) => {
+ const newErrors = collapsedData.new_errors.map((error) => {
return {
header: __('New'),
id: uniqueId('new-error-'),
@@ -92,7 +91,7 @@ export default {
};
});
- const existingErrors = existing_errors.map((error) => {
+ const existingErrors = collapsedData.existing_errors.map((error) => {
return {
id: uniqueId('existing-error-'),
text: this.formatText(error.code),
@@ -105,7 +104,7 @@ export default {
};
});
- const resolvedErrors = resolved_errors.map((error) => {
+ const resolvedErrors = collapsedData.resolved_errors.map((error) => {
return {
id: uniqueId('resolved-error-'),
text: this.formatText(error.code),
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
index 4ffd06de61f..6896f8831e8 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/utils.js
@@ -51,14 +51,14 @@ export const recentFailuresTextBuilder = (summary = {}) => {
return i18n.recentFailureSummary(recentlyFailed, failed);
};
-export const reportSubTextBuilder = ({ suite_errors, summary }) => {
- if (suite_errors?.head || suite_errors?.base) {
+export const reportSubTextBuilder = ({ suite_errors: suiteErrors, summary }) => {
+ if (suiteErrors?.head || suiteErrors?.base) {
const errors = [];
- if (suite_errors?.head) {
- errors.push(`${i18n.headReportParsingError} ${suite_errors.head}`);
+ if (suiteErrors?.head) {
+ errors.push(`${i18n.headReportParsingError} ${suiteErrors.head}`);
}
- if (suite_errors?.base) {
- errors.push(`${i18n.baseReportParsingError} ${suite_errors.base}`);
+ if (suiteErrors?.base) {
+ errors.push(`${i18n.baseReportParsingError} ${suiteErrors.base}`);
}
return errors.join('<br />');
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index 627ddb0445e..d964b4bacac 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -20,13 +20,6 @@ export default {
this.mr.preventMerge,
);
},
- shouldShowMergeControls() {
- if (this.glFeatures.restructuredMrWidget) {
- return this.restructuredWidgetShowMergeButtons;
- }
-
- return this.isMergeAllowed || this.isAutoMergeAvailable;
- },
mergeDisabledText() {
if (this.pipeline?.status === PIPELINE_SKIPPED_STATUS) {
return MERGE_DISABLED_SKIPPED_PIPELINE_TEXT;
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 3e0ac236fdf..1e25143e15c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -1,7 +1,6 @@
<script>
import { GlSafeHtmlDirective } from '@gitlab/ui';
import { isEmpty } from 'lodash';
-import securityReportExtension from 'ee_else_ce/vue_merge_request_widget/extensions/security_reports';
import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
import MrWidgetApprovals from 'ee_else_ce/vue_merge_request_widget/components/approvals/approvals.vue';
import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
@@ -17,7 +16,6 @@ import { setFaviconOverlay } from '../lib/utils/favicon';
import Loading from './components/loading.vue';
import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue';
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
-import WidgetRelatedLinks from './components/mr_widget_related_links.vue';
import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue';
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import ArchivedState from './components/states/mr_widget_archived.vue';
@@ -40,6 +38,7 @@ import ShaMismatch from './components/states/sha_mismatch.vue';
import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
import WorkInProgressState from './components/states/work_in_progress.vue';
import ExtensionsContainer from './components/extensions/container';
+import WidgetContainer from './components/widget/app.vue';
import { STATE_MACHINE, stateToComponentMap } from './constants';
import eventHub from './event_hub';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
@@ -59,9 +58,9 @@ export default {
components: {
Loading,
ExtensionsContainer,
+ WidgetContainer,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
MrWidgetPipelineContainer,
- 'mr-widget-related-links': WidgetRelatedLinks,
MrWidgetAlertMessage,
'mr-widget-merged': MergedState,
'mr-widget-closed': ClosedState,
@@ -73,9 +72,7 @@ export default {
'mr-widget-nothing-to-merge': NothingToMergeState,
'mr-widget-not-allowed': NotAllowedState,
'mr-widget-missing-branch': MissingBranchState,
- 'mr-widget-ready-to-merge': window.gon?.features?.restructuredMrWidget
- ? () => import('./components/states/new_ready_to_merge.vue')
- : ReadyToMergeState,
+ 'mr-widget-ready-to-merge': () => import('./components/states/new_ready_to_merge.vue'),
'sha-mismatch': ShaMismatch,
'mr-widget-checking': CheckingState,
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
@@ -163,12 +160,6 @@ export default {
shouldRenderCodeQuality() {
return this.mr?.codequalityReportsPath;
},
- shouldRenderRelatedLinks() {
- return (
- (Boolean(this.mr.relatedLinks) || this.mr.divergedCommitsCount > 0) &&
- !this.mr.isNothingToMergeState
- );
- },
shouldRenderSourceBranchRemovalStatus() {
return (
!this.mr.canRemoveSourceBranch &&
@@ -239,9 +230,6 @@ export default {
shouldShowCodeQualityExtension() {
return window.gon?.features?.refactorCodeQualityExtension;
},
- isRestructuredMrWidgetEnabled() {
- return window.gon?.features?.restructuredMrWidget;
- },
},
watch: {
'mr.machineValue': {
@@ -275,11 +263,6 @@ export default {
this.registerTestReportExtension();
}
},
- shouldRenderSecurityReport(newVal) {
- if (newVal) {
- this.registerSecurityReportExtension();
- }
- },
},
mounted() {
MRWidgetService.fetchInitialData()
@@ -535,11 +518,6 @@ export default {
registerExtension(testReportExtension);
}
},
- registerSecurityReportExtension() {
- if (this.shouldRenderSecurityReport && this.shouldShowSecurityExtension) {
- registerExtension(securityReportExtension);
- }
- },
},
};
</script>
@@ -600,7 +578,11 @@ export default {
</template>
</mr-widget-alert-message>
</div>
+
<extensions-container :mr="mr" />
+
+ <widget-container v-if="mr" :mr="mr" />
+
<grouped-codequality-reports-app
v-if="shouldRenderCodeQuality && !shouldShowCodeQualityExtension"
:head-blob-path="mr.headBlobPath"
@@ -638,23 +620,7 @@ export default {
<div class="mr-widget-section" data-qa-selector="mr_widget_content">
<component :is="componentName" :mr="mr" :service="service" />
- <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"
- :diverged-commits-count="mr.divergedCommitsCount"
- :target-branch-path="mr.targetBranchPath"
- class="mr-info-list gl-ml-7 gl-pb-5"
- />
-
- <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
- </div>
+ <ready-to-merge v-if="mr.commitsCount" :mr="mr" :service="service" />
</div>
</div>
<mr-widget-pipeline-container
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
index efc0673bc26..54770e6579a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql
@@ -1,11 +1,9 @@
fragment ReadyToMerge on Project {
- __typename
id
onlyAllowMergeIfPipelineSucceeds
mergeRequestsFfOnlyEnabled
squashReadOnly
mergeRequest(iid: $iid) {
- __typename
id
autoMergeEnabled
shouldRemoveSourceBranch
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index 18d955652ba..7a458f9ce7e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -27,8 +27,6 @@ export default function deviseState() {
return stateKey.shaMismatch;
} else if (this.autoMergeEnabled && !this.mergeError) {
return stateKey.autoMergeEnabled;
- } else if (!this.canMerge && !window.gon?.features?.restructuredMrWidget) {
- return stateKey.notAllowedToMerge;
} else if (this.canBeMerged) {
return stateKey.readyToMerge;
}
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 03c9a01cc7a..146cf7e11a7 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
@@ -33,7 +33,6 @@ export default class MergeRequestStore {
this.setData(data);
this.initCodeQualityReport(data);
- this.initSecurityReport(data);
this.setGitpodData(data);
}
@@ -42,19 +41,6 @@ export default class MergeRequestStore {
this.codeQuality = data.codequality_reports_path;
}
- initSecurityReport(data) {
- // TODO: check if gl.mrWidgetData can be safely removed after we migrate to the
- // widget extension.
- this.securityReportPaths = {
- apiFuzzingReportPath: data.api_fuzzing_comparison_path,
- coverageFuzzingReportPath: data.coverage_fuzzing_comparison_path,
- sastReportPath: data.sast_comparison_path,
- dastReportPath: data.dast_comparison_path,
- secretDetectionReportPath: data.secret_detection_comparison_path,
- dependencyScanningReportPath: data.dependency_scanning_comparison_path,
- };
- }
-
setData(data, isRebased) {
this.initApprovals();