diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-15 18:09:53 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-08-15 18:09:53 +0300 |
commit | 51d5328e82229d69456d3a43dd2cf10518bf64c7 (patch) | |
tree | cca8c7aaea10c92398e03ae182b76c5cc514185c /app/assets/javascripts/vue_merge_request_widget | |
parent | 14771dc276c9cfdeed1a3915ee29301cd848b475 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget')
14 files changed, 373 insertions, 268 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 266f1fb594b..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,7 +49,16 @@ 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.state === 'closed') { @@ -68,10 +77,17 @@ export default { }, 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, @@ -82,16 +98,30 @@ export default { <span> <gl-sprintf :message="message"> <template #commitCount> - <span class="commits-count-message">{{ commitsCountMessage }}</span> + <gl-sprintf :message="commitsCountMessage"> + <template #strong="{ content }"> + <span class="gl-font-weight-bold">{{ content }}</span> + </template> + </gl-sprintf> </template> <template #mergeCommitCount> - <span>{{ $options.mergeCommitCount }}</span> + <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="isSquashEnabled"> {{ squashCommitMessage }}</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> <span class="label-branch">{{ mergeCommitSha }}</span> 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/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/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue index 63bd8f3d8dc..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,5 +1,5 @@ <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'; @@ -9,6 +9,7 @@ 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', @@ -28,8 +29,8 @@ export default { MrWidgetAuthor, GlSkeletonLoader, GlIcon, - GlButton, GlSprintf, + StateContainer, }, mixins: [autoMergeMixin, glFeatureFlagMixin(), mergeRequestQueryVariablesMixin], props: { @@ -77,6 +78,26 @@ export default { autoMergeStrategy() { return (this.glFeatures.mergeRequestWidgetGraphql ? this.state : this.mr).autoMergeStrategy; }, + actions() { + const actions = []; + + 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: { cancelAutomaticMerge() { @@ -130,38 +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> - </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_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue index 7652d7049f2..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,25 +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! 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! 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"> {{ @@ -114,23 +112,30 @@ export default { }} </span> </span> - <gl-button - v-if="showResolveButton" - :href="mr.conflictResolutionPath" - size="small" - data-testid="resolve-conflicts-button" - > - {{ s__('mrWidget|Resolve conflicts') }} - </gl-button> - <gl-button - v-if="canMerge" - size="small" - 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_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue index 19df346759f..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,5 +1,5 @@ <script> -import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; +import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; import api from '~/api'; import createFlash from '~/flash'; import { s__, __ } from '~/locale'; @@ -7,6 +7,7 @@ import { OPEN_REVERT_MODAL, OPEN_CHERRY_PICK_MODAL } from '~/projects/commit/con import modalEventHub from '~/projects/commit/event_hub'; import eventHub from '../../event_hub'; import MrWidgetAuthorTime from '../mr_widget_author_time.vue'; +import StateContainer from '../state_container.vue'; export default { name: 'MRWidgetMerged', @@ -16,7 +17,7 @@ export default { components: { MrWidgetAuthorTime, GlIcon, - GlButton, + StateContainer, }, props: { mr: { @@ -72,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')); @@ -115,68 +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> - </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_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue index 0880fd81500..d25d1ade7eb 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: { @@ -76,6 +76,10 @@ export default { return this.mr.targetBranch; }, status() { + if (this.isLoading) { + return undefined; + } + if (this.rebaseInProgress || this.isMakingRequest) { return 'loading'; } @@ -148,69 +152,71 @@ 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! 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! 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 > - <span - v-if="!rebasingError" - class="gl-ml-0! gl-text-body! 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 - :loading="isMakingRequest" - variant="confirm" - size="small" - data-qa-selector="mr_rebase_button" - data-testid="standard-rebase-button" - class="gl-ml-3!" - @click="rebase" - > - {{ __('Rebase') }} - </gl-button> - <gl-button - v-if="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 + v-if="showRebaseWithoutCi" + :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/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index 884fc666276..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 @@ -335,6 +335,9 @@ export default { ? __('Did not delete the source branch.') : __('Source branch will not be deleted.'); }, + showMergeDetailsHeader() { + return ['readyToMerge'].indexOf(this.mr.state) >= 0; + }, }, mounted() { if (this.glFeatures.mergeRequestWidgetGraphql) { @@ -524,7 +527,7 @@ export default { </div> </div> <template v-else> - <div class="mr-widget-body media mr-widget-body-line-height-1"> + <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="shouldShowMergeControls" class="gl-align-self-start"> @@ -651,13 +654,13 @@ export default { </div> <div v-if="!shouldShowMergeControls" - class="gl-w-full gl-order-n1 gl-text-gray-500" + class="gl-w-full gl-order-n1 mr-widget-merge-details" data-qa-selector="merged_status_content" > - <strong v-if="mr.state !== 'closed'"> + <p v-if="showMergeDetailsHeader" class="gl-mb-3 gl-text-gray-900"> {{ __('Merge details') }} - </strong> - <ul class="gl-pl-4 gl-m-0"> + </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')" 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 06f70bc456e..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,13 +1,13 @@ <script> import { GlButton } from '@gitlab/ui'; 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, @@ -22,24 +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! 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/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue index 7e9ebcf0b2e..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,13 +1,13 @@ <script> import { GlButton } from '@gitlab/ui'; 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, }, props: { mr: { @@ -24,30 +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! 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" variant="confirm" category="secondary" - @click="jumpToFirstUnresolvedDiscussion" > - {{ 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" + 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 501aee1a18d..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,26 +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! 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> |