diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-12-20 16:37:47 +0300 |
commit | aee0a117a889461ce8ced6fcf73207fe017f1d99 (patch) | |
tree | 891d9ef189227a8445d83f35c1b0fc99573f4380 /app/assets/javascripts/vue_merge_request_widget | |
parent | 8d46af3258650d305f53b819eabf7ab18d22f59e (diff) |
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget')
32 files changed, 308 insertions, 116 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue index f4f611dfd1b..e115710b5d1 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue @@ -1,7 +1,7 @@ <script> import { GlLink, GlTooltipDirective } from '@gitlab/ui'; import { __ } from '~/locale'; -import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; import timeagoMixin from '~/vue_shared/mixins/timeago'; import { MANUAL_DEPLOY, 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 6f10f788952..549cf64fb08 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 @@ -9,17 +9,20 @@ import { GlIntersectionObserver, } from '@gitlab/ui'; import { once } from 'lodash'; +import * as Sentry from '@sentry/browser'; import api from '~/api'; import { sprintf, s__, __ } from '~/locale'; import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue'; -import { EXTENSION_ICON_CLASS } from '../../constants'; +import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants'; import StatusIcon from './status_icon.vue'; import Actions from './actions.vue'; +import { generateText } from './utils'; export const LOADING_STATES = { collapsedLoading: 'collapsedLoading', collapsedError: 'collapsedError', expandedLoading: 'expandedLoading', + expandedError: 'expandedError', }; export default { @@ -40,8 +43,8 @@ export default { data() { return { loadingState: LOADING_STATES.collapsedLoading, - collapsedData: null, - fullData: null, + collapsedData: {}, + fullData: [], isCollapsed: true, showFade: false, }; @@ -53,6 +56,9 @@ export default { widgetLoadingText() { return this.$options.i18n?.loading || __('Loading...'); }, + widgetErrorText() { + return this.$options.i18n?.error || __('Failed to load'); + }, isLoadingSummary() { return this.loadingState === LOADING_STATES.collapsedLoading; }, @@ -60,11 +66,16 @@ export default { return this.loadingState === LOADING_STATES.expandedLoading; }, isCollapsible() { - if (this.isLoadingSummary) { - return false; - } - - return true; + return !this.isLoadingSummary && this.loadingState !== LOADING_STATES.collapsedError; + }, + hasFullData() { + return this.fullData.length > 0; + }, + hasFetchError() { + return ( + this.loadingState === LOADING_STATES.collapsedError || + this.loadingState === LOADING_STATES.expandedError + ); }, collapseButtonLabel() { return sprintf( @@ -75,6 +86,7 @@ export default { ); }, statusIconName() { + if (this.hasFetchError) return EXTENSION_ICONS.error; if (this.isLoadingSummary) return null; return this.statusIcon(this.collapsedData); @@ -82,6 +94,20 @@ export default { tertiaryActionsButtons() { return this.tertiaryButtons ? this.tertiaryButtons() : undefined; }, + hydratedSummary() { + const structuredOutput = this.summary(this.collapsedData); + const summary = { + subject: generateText( + typeof structuredOutput === 'string' ? structuredOutput : structuredOutput.subject, + ), + }; + + if (structuredOutput.meta) { + summary.meta = generateText(structuredOutput.meta); + } + + return summary; + }, }, watch: { isCollapsed(newVal) { @@ -93,15 +119,7 @@ export default { }, }, mounted() { - this.fetchCollapsedData(this.$props) - .then((data) => { - this.collapsedData = data; - this.loadingState = null; - }) - .catch((e) => { - this.loadingState = LOADING_STATES.collapsedError; - throw e; - }); + this.loadCollapsedData(); }, methods: { triggerRedisTracking: once(function triggerRedisTracking() { @@ -114,8 +132,22 @@ export default { this.triggerRedisTracking(); }, + loadCollapsedData() { + this.loadingState = LOADING_STATES.collapsedLoading; + + this.fetchCollapsedData(this.$props) + .then((data) => { + this.collapsedData = data; + this.loadingState = null; + }) + .catch((e) => { + this.loadingState = LOADING_STATES.collapsedError; + + Sentry.captureException(e); + }); + }, loadAllData() { - if (this.fullData) return; + if (this.hasFullData) return; this.loadingState = LOADING_STATES.expandedLoading; @@ -125,10 +157,14 @@ export default { this.fullData = data; }) .catch((e) => { - this.loadingState = null; - throw e; + this.loadingState = LOADING_STATES.expandedError; + + Sentry.captureException(e); }); }, + isArray(arr) { + return Array.isArray(arr); + }, appear(index) { if (index === this.fullData.length - 1) { this.showFade = false; @@ -139,6 +175,7 @@ export default { this.showFade = true; } }, + generateText, }, EXTENSION_ICON_CLASS, }; @@ -153,20 +190,29 @@ export default { :icon-name="statusIconName" /> <div - class="media-body gl-display-flex gl-flex-direction-row!" + 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"> <template v-if="isLoadingSummary">{{ widgetLoadingText }}</template> - <div v-else v-safe-html="summary(collapsedData)"></div> + <template v-else-if="hasFetchError">{{ widgetErrorText }}</template> + <div v-else> + <span v-safe-html="hydratedSummary.subject"></span> + <template v-if="hydratedSummary.meta"> + <br /> + <span v-safe-html="hydratedSummary.meta" class="gl-font-sm"></span> + </template> + </div> </div> <actions :widget="$options.label || $options.name" :tertiary-buttons="tertiaryActionsButtons" /> - <div class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6"> + <div + v-if="isCollapsible" + class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6" + > <gl-button - v-if="isCollapsible" v-gl-tooltip :title="collapseButtonLabel" :aria-expanded="`${!isCollapsed}`" @@ -189,7 +235,7 @@ export default { <gl-loading-icon size="sm" inline /> {{ __('Loading...') }} </div> <smart-virtual-list - v-else-if="fullData" + v-else-if="hasFullData" :length="fullData.length" :remain="20" :size="32" @@ -203,37 +249,64 @@ export default { :class="{ 'gl-border-b-solid gl-border-b-1 gl-border-gray-100': index !== fullData.length - 1, }" - class="gl-display-flex gl-align-items-center gl-py-3 gl-pl-7" + class="gl-py-3 gl-pl-7" data-testid="extension-list-item" > - <status-icon v-if="data.icon" :icon-name="data.icon.name" :size="12" class="gl-pl-0" /> - <gl-intersection-observer - :options="{ rootMargin: '100px', thresholds: 0.1 }" - class="gl-flex-wrap gl-display-flex gl-w-full" - @appear="appear(index)" - @disappear="disappear(index)" - > - <div - v-safe-html="data.text" - class="gl-mr-4 gl-display-flex gl-align-items-center" - ></div> - <div v-if="data.link"> - <gl-link :href="data.link.href">{{ data.link.text }}</gl-link> + <div class="gl-w-full"> + <div v-if="data.header" class="gl-mb-2"> + <template v-if="isArray(data.header)"> + <component + :is="headerI === 0 ? 'strong' : 'span'" + v-for="(header, headerI) in data.header" + :key="headerI" + v-safe-html="generateText(header)" + class="gl-display-block" + /> + </template> + <strong v-else v-safe-html="generateText(data.header)"></strong> + </div> + <div class="gl-display-flex"> + <status-icon + v-if="data.icon" + :icon-name="data.icon.name" + :size="12" + class="gl-pl-0" + /> + <gl-intersection-observer + :options="{ rootMargin: '100px', thresholds: 0.1 }" + class="gl-w-full" + @appear="appear(index)" + @disappear="disappear(index)" + > + <div class="gl-flex-wrap gl-display-flex gl-w-full"> + <div class="gl-mr-4 gl-display-flex gl-align-items-center"> + <p v-safe-html="generateText(data.text)" class="gl-m-0"></p> + </div> + <div v-if="data.link"> + <gl-link :href="data.link.href">{{ data.link.text }}</gl-link> + </div> + <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'"> + {{ data.badge.text }} + </gl-badge> + <actions + :widget="$options.label || $options.name" + :tertiary-buttons="data.actions" + class="gl-ml-auto" + /> + </div> + <p + v-if="data.subtext" + v-safe-html="generateText(data.subtext)" + class="gl-m-0 gl-font-sm" + ></p> + </gl-intersection-observer> </div> - <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'"> - {{ data.badge.text }} - </gl-badge> - <actions - :widget="$options.label || $options.name" - :tertiary-buttons="data.actions" - class="gl-ml-auto" - /> - </gl-intersection-observer> + </div> </li> </smart-virtual-list> <div :class="{ show: showFade }" - class="fade mr-extenson-scrim gl-absolute gl-left-0 gl-bottom-0 gl-w-full gl-h-7" + class="fade mr-extenson-scrim gl-absolute gl-left-0 gl-bottom-0 gl-w-full gl-h-7 gl-pointer-events-none" ></div> </div> </section> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js new file mode 100644 index 00000000000..8ba13cf8252 --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js @@ -0,0 +1,62 @@ +const TEXT_STYLES = { + success: { + start: '%{success_start}', + end: '%{success_end}', + }, + danger: { + start: '%{danger_start}', + end: '%{danger_end}', + }, + critical: { + start: '%{critical_start}', + end: '%{critical_end}', + }, + same: { + start: '%{same_start}', + end: '%{same_end}', + }, + strong: { + start: '%{strong_start}', + end: '%{strong_end}', + }, + small: { + start: '%{small_start}', + end: '%{small_end}', + }, +}; + +const getStartTag = (tag) => TEXT_STYLES[tag].start; +const textStyleTags = { + [getStartTag('success')]: '<span class="gl-font-weight-bold gl-text-green-500">', + [getStartTag('danger')]: '<span class="gl-font-weight-bold gl-text-red-500">', + [getStartTag('critical')]: '<span class="gl-font-weight-bold gl-text-red-800">', + [getStartTag('same')]: '<span class="gl-font-weight-bold gl-text-gray-700">', + [getStartTag('strong')]: '<span class="gl-font-weight-bold">', + [getStartTag('small')]: '<span class="gl-font-sm">', +}; + +export const generateText = (text) => { + if (typeof text !== 'string') return null; + + return text + .replace( + new RegExp( + `(${Object.values(TEXT_STYLES) + .reduce((acc, i) => [...acc, ...Object.values(i)], []) + .join('|')})`, + 'gi', + ), + (replace) => { + const replacement = textStyleTags[replace]; + + // If the replacement tag ends with a `_end` then we can just return `</span>` + // unless we have a replacement, for cases were we want to change the HTML tag + if (!replacement && replace.endsWith('_end}')) { + return '</span>'; + } + + return replacement; + }, + ) + .replace(/%{([a-z]|_)+}/g, ''); // Filter out any tags we don't know about +}; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue index 9070cb1fe65..235a200b747 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue @@ -13,7 +13,7 @@ import { import { constructWebIDEPath } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import clipboardButton from '~/vue_shared/components/clipboard_button.vue'; -import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; import WebIdeLink from '~/vue_shared/components/web_ide_link.vue'; import MrWidgetHowToMergeModal from './mr_widget_how_to_merge_modal.vue'; import MrWidgetIcon from './mr_widget_icon.vue'; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index f7c952f9ef6..c0b80eef082 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -15,7 +15,7 @@ import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mi import PipelineArtifacts from '~/pipelines/components/pipelines_list/pipelines_artifacts.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; -import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; import { MT_MERGE_STRATEGY } from '../constants'; export default { 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 c314261d3f5..730d11b1208 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,9 +1,13 @@ <script> +import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; import { s__, n__ } from '~/locale'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; export default { name: 'MRWidgetRelatedLinks', + directives: { + SafeHtml, + }, mixins: [glFeatureFlagMixin()], props: { relatedLinks: { @@ -43,14 +47,14 @@ export default { :class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }" > {{ closesText }} - <span v-html="relatedLinks.closing /* eslint-disable-line vue/no-v-html */"></span> + <span v-safe-html="relatedLinks.closing"></span> </p> <p v-if="relatedLinks.mentioned" :class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }" > {{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }} - <span v-html="relatedLinks.mentioned /* eslint-disable-line vue/no-v-html */"></span> + <span v-safe-html="relatedLinks.mentioned"></span> </p> <p v-if="relatedLinks.assignToMe && showAssignToMe" 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 3eda2828e97..18761d04c2e 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 @@ -41,7 +41,6 @@ export default { rows="7" @input="$emit('input', $event.target.value)" ></textarea> - <slot name="text-muted"></slot> </div> </li> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue index 503ddf8a396..ce572f8b0bf 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue @@ -9,7 +9,7 @@ export default { pipelineFailed: s__( 'mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure.', ), - approvalNeeded: s__('mrWidget|You can only merge once this merge request is approved.'), + approvalNeeded: s__('mrWidget|Merge blocked: this merge request must be approved.'), unresolvedDiscussions: s__('mrWidget|Merge blocked: all threads must be resolved.'), }, components: { 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 29c26f4fb3e..13b1e49f44e 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 @@ -20,7 +20,7 @@ export default { </div> <div class="media-body"> <span class="bold"> - {{ s__('mrWidget|This project is archived, write access has been disabled') }} + {{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }} </span> </div> </div> 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 1596f852b74..7a002d41ac0 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 @@ -117,11 +117,12 @@ export default { </span> <template v-else> <span class="bold"> - {{ s__('mrWidget|There are merge conflicts') }}<span v-if="!canMerge">.</span> + {{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }} <span v-if="!canMerge"> {{ - s__(`mrWidget|Resolve these conflicts or ask someone - with write access to this repository to merge it locally`) + s__( + `mrWidget|Users who can write to the source or target branches can resolve the conflicts.`, + ) }} </span> </span> 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 9f2870d8d69..01e8303f513 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 @@ -121,9 +121,6 @@ export default { if (res.merge_error && res.merge_error.length) { this.rebasingError = res.merge_error; - createFlash({ - message: __('Something went wrong. Please try again.'), - }); } eventHub.$emit('MRWidgetRebaseSuccess'); 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 d2cc99302a9..8830128b7d6 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 @@ -181,9 +181,16 @@ export default { return this.mr.canRemoveSourceBranch; }, commitTemplateHelpPage() { - return helpPagePath('user/project/merge_requests/commit_templates.md', { - anchor: 'merge-commit-message-template', - }); + return helpPagePath('user/project/merge_requests/commit_templates.md'); + }, + commitTemplateHintText() { + if (this.shouldShowSquashEdit && this.shouldShowMergeEdit) { + return this.$options.i18n.mergeAndSquashCommitTemplatesHintText; + } + if (this.shouldShowSquashEdit) { + return this.$options.i18n.squashCommitTemplateHintText; + } + return this.$options.i18n.mergeCommitTemplateHintText; }, commits() { if (this.glFeatures.mergeRequestWidgetGraphql) { @@ -287,7 +294,7 @@ export default { return false; } - return enableSquashBeforeMerge && this.commitsCount > 1; + return enableSquashBeforeMerge; }, shouldShowMergeControls() { if (this.glFeatures.restructuredMrWidget) { @@ -509,6 +516,12 @@ export default { mergeCommitTemplateHintText: s__( 'mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}', ), + squashCommitTemplateHintText: s__( + 'mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}', + ), + mergeAndSquashCommitTemplatesHintText: s__( + 'mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}', + ), }, }; </script> @@ -590,13 +603,7 @@ export default { :class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }" class="gl-display-flex gl-align-items-center gl-flex-wrap" > - <merge-train-helper-icon - v-if="shouldRenderMergeTrainHelperIcon" - :merge-train-when-pipeline-succeeds-docs-path=" - mr.mergeTrainWhenPipelineSucceedsDocsPath - " - class="gl-mx-3" - /> + <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" /> <gl-form-checkbox v-if="canRemoveSourceBranch" @@ -680,23 +687,22 @@ export default { :label="__('Merge commit message')" input-id="merge-message-edit" class="gl-m-0! gl-p-0!" - > - <template #text-muted> - <p class="form-text text-muted"> - <gl-sprintf :message="$options.i18n.mergeCommitTemplateHintText"> - <template #link="{ content }"> - <gl-link - :href="commitTemplateHelpPage" - class="inline-link" - target="_blank" - > - {{ content }} - </gl-link> - </template> - </gl-sprintf> - </p> - </template> - </commit-edit> + /> + <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 @@ -798,19 +804,18 @@ export default { v-model="commitMessage" :label="__('Merge commit message')" input-id="merge-message-edit" - > - <template #text-muted> - <p class="form-text text-muted"> - <gl-sprintf :message="$options.i18n.mergeCommitTemplateHintText"> - <template #link="{ content }"> - <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank"> - {{ content }} - </gl-link> - </template> - </gl-sprintf> - </p> - </template> - </commit-edit> + /> + <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> 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 fa4f8b76cb9..ba831a33b73 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 @@ -165,13 +165,12 @@ export default { <div class="mr-widget-body media"> <status-icon :show-disabled-button="canUpdate" status="warning" /> <div class="media-body"> - <div class="gl-ml-3 float-left"> + <div class="float-left"> <span class="gl-font-weight-bold"> - {{ __('This merge request is still a draft.') }} + {{ + __("Merge blocked: merge request must be marked as ready. It's still marked as draft.") + }} </span> - <span class="gl-display-block text-muted">{{ - __("Draft merge requests can't be merged.") - }}</span> </div> <gl-button v-if="canUpdate" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue index 87a310efe78..1e5f7361966 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue @@ -20,8 +20,8 @@ export default { 'Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete', ), generationErrored: s__('Terraform|Generating the report caused an error.'), - namedReportFailed: s__('Terraform|The report %{name} failed to generate.'), - namedReportGenerated: s__('Terraform|The report %{name} was generated in your pipelines.'), + namedReportFailed: s__('Terraform|The job %{name} failed to generate a report.'), + namedReportGenerated: s__('Terraform|The job %{name} generated a report.'), reportFailed: s__('Terraform|A report failed to generate.'), reportGenerated: s__('Terraform|A report was generated in your pipelines.'), }, diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js index d0c6cf12e25..2edccce7f4e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/constants.js +++ b/app/assets/javascripts/vue_merge_request_widget/constants.js @@ -50,6 +50,18 @@ export const MERGE_ACTIVE_STATUS_PHRASES = [ message: s__('mrWidget|Merging! This is going to be great…'), emoji: 'heart_eyes', }, + { + message: s__('mrWidget|Merging! Lift-off in 5… 4… 3…'), + emoji: 'rocket', + }, + { + message: s__('mrWidget|Merging! The changes are leaving the station…'), + emoji: 'bullettrain_front', + }, + { + message: s__('mrWidget|Merging! Take a deep breath and relax…'), + emoji: 'sunglasses', + }, ]; const STATE_MACHINE = { @@ -146,4 +158,7 @@ export const EXTENSION_ICON_CLASS = { severityUnknown: 'gl-text-gray-400', }; +export const EXTENSION_SUMMARY_FAILED_CLASS = 'gl-text-red-500'; +export const EXTENSION_SUMMARY_NEUTRAL_CLASS = 'gl-text-gray-700'; + export { STATE_MACHINE }; diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js index 9cbc0b0e5d1..ba3336df2eb 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js @@ -2,6 +2,7 @@ import { EXTENSION_ICONS } from '../constants'; import issuesCollapsedQuery from './issues_collapsed.query.graphql'; import issuesQuery from './issues.query.graphql'; +import { n__, sprintf } from '~/locale'; export default { // Give the extension a name @@ -20,7 +21,14 @@ export default { // Small summary text to be displayed in the collapsed state // Receives the collapsed data as an argument summary(count) { - return 'Summary text<br/>Second line'; + return sprintf( + n__( + 'ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} change', + 'ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} changes', + changesFound, + ), + { changesFound }, + ); }, // Status icon to be used next to the summary text // Receives the collapsed data as an argument @@ -57,9 +65,13 @@ export default { .query({ query: issuesQuery, variables: { projectPath: targetProjectFullPath } }) .then(({ data }) => { // Return some transformed data to be rendered in the expanded state - return data.project.issues.nodes.map((issue) => ({ + return data.project.issues.nodes.map((issue, i) => ({ id: issue.id, // Required: The ID of the object - text: issue.title, // Required: The text to get used on each row + header: ['New', 'This is an %{strong_start}issue%{strong_end} row'], + text: + '%{critical_start}1 Critical%{critical_end}, %{danger_start}1 High%{danger_end}, and %{strong_start}1 Other%{strong_end}. %{small_start}Some smaller text%{small_end}', // Required: The text to get used on each row + subtext: + 'Reported resource changes: %{strong_start}2%{strong_end} to add, 0 to change, 0 to delete', // Optional: The sub-text to get displayed below each rows main content // Icon to get rendered on the side of each row icon: { // Required: Name maps to an icon in GitLabs SVG diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql index 690f571c083..5c54560bd02 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql @@ -1,5 +1,6 @@ query getAllIssues($projectPath: ID!) { project(fullPath: $projectPath) { + id issues { nodes { id diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql index da1cace4598..bf278e1ea85 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql @@ -1,5 +1,6 @@ query getProjectIssues($projectPath: ID!) { project(fullPath: $projectPath) { + id issues { count } 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 83789f10285..fa618756bb5 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 @@ -1,6 +1,8 @@ import { __ } from '~/locale'; -export const MERGE_DISABLED_TEXT = __('You can only merge once the items above are resolved.'); +export const MERGE_DISABLED_TEXT = __( + 'Merge blocked: all merge request dependencies must be merged or closed.', +); export const MERGE_DISABLED_SKIPPED_PIPELINE_TEXT = __( "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue.", ); diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql index bfb1517be81..0b8396b4461 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql @@ -1,9 +1,11 @@ query getState($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id archived onlyAllowMergeIfPipelineSucceeds mergeRequest(iid: $iid) { + id autoMergeEnabled commitCount conflicts diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql index ae2a67440fe..7ca3ff39fbe 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql @@ -1,6 +1,8 @@ query userPermissionsQuery($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id userPermissions { canMerge pushToSourceBranch diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql index ad715599eb1..fc25e699e39 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql @@ -1,4 +1,5 @@ fragment autoMergeEnabled on MergeRequest { + id autoMergeStrategy mergeUser { id diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql index e0215fbd969..2d79d35cf24 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql @@ -2,6 +2,7 @@ query autoMergeEnabled($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { ...autoMergeEnabled } diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql index 2fe0d174b67..da8aeab9dcb 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql @@ -1,6 +1,8 @@ query autoMergeFailedQuery($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id mergeError } } diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql index e66ac01ab12..faf21b28f86 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql @@ -1,6 +1,8 @@ query workInProgress($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id shouldBeRebased sourceBranchProtected } diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql index 0983c28448e..54f2233439f 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql @@ -1,6 +1,8 @@ query mrUserPermission($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id userPermissions { updateMergeRequest } diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql index ea95218aec6..4d87d55f671 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql @@ -1,6 +1,8 @@ query missingBranchQuery($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id sourceBranchExists } } diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql index 21c3ffd8321..73c9e77b7bc 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql @@ -1,6 +1,8 @@ query getReadyToMergeStatus($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id userPermissions { canMerge } 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 b2a1be5c5a9..d85794f7245 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,8 +1,10 @@ fragment ReadyToMerge on Project { + id onlyAllowMergeIfPipelineSucceeds mergeRequestsFfOnlyEnabled squashReadOnly mergeRequest(iid: $iid) { + id autoMergeEnabled shouldRemoveSourceBranch forceRemoveSourceBranch @@ -26,6 +28,7 @@ fragment ReadyToMerge on Project { mergeError commitsWithoutMergeCommits { nodes { + id sha shortId title diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql index a8c7d2610bf..283177267d4 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql @@ -1,6 +1,8 @@ query rebaseQuery($projectPath: ID!, $iid: String!) { project(fullPath: $projectPath) { + id mergeRequest(iid: $iid) { + id rebaseInProgress targetBranch userPermissions { diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql index 200fb1b7ca5..022629bb802 100644 --- a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql +++ b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql @@ -1,6 +1,7 @@ mutation toggleDraftStatus($projectPath: ID!, $iid: String!, $draft: Boolean!) { mergeRequestSetDraft(input: { projectPath: $projectPath, iid: $iid, draft: $draft }) { mergeRequest { + id mergeableDiscussionsState title draft 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 10a2907c81a..57af869a0ba 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 @@ -59,7 +59,6 @@ export default class MergeRequestStore { this.sourceBranch = data.source_branch; this.sourceBranchProtected = data.source_branch_protected; this.conflictsDocsPath = data.conflicts_docs_path; - this.mergeTrainWhenPipelineSucceedsDocsPath = data.merge_train_when_pipeline_succeeds_docs_path; this.commitMessage = data.default_merge_commit_message; this.shortMergeCommitSha = data.short_merged_commit_sha; this.mergeCommitSha = data.merged_commit_sha; |