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/extensions/base.vue157
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js27
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue86
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js66
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue6
14 files changed, 379 insertions, 88 deletions
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
new file mode 100644
index 00000000000..eff26729fa7
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -0,0 +1,157 @@
+<script>
+import { GlButton, GlLoadingIcon, GlIcon, GlLink, GlBadge, GlSafeHtmlDirective } from '@gitlab/ui';
+import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
+import StatusIcon from '../mr_widget_status_icon.vue';
+
+export const LOADING_STATES = {
+ collapsedLoading: 'collapsedLoading',
+ collapsedError: 'collapsedError',
+ expandedLoading: 'expandedLoading',
+};
+
+export default {
+ components: {
+ GlButton,
+ GlLoadingIcon,
+ GlIcon,
+ GlLink,
+ GlBadge,
+ SmartVirtualList,
+ StatusIcon,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ data() {
+ return {
+ loadingState: LOADING_STATES.collapsedLoading,
+ collapsedData: null,
+ fullData: null,
+ isCollapsed: true,
+ };
+ },
+ computed: {
+ isLoadingSummary() {
+ return this.loadingState === LOADING_STATES.collapsedLoading;
+ },
+ isLoadingExpanded() {
+ return this.loadingState === LOADING_STATES.expandedLoading;
+ },
+ isCollapsible() {
+ if (this.isLoadingSummary) {
+ return false;
+ }
+
+ return true;
+ },
+ statusIconName() {
+ if (this.isLoadingSummary) {
+ return 'loading';
+ }
+
+ if (this.loadingState === LOADING_STATES.collapsedError) {
+ return 'warning';
+ }
+
+ return this.statusIcon(this.collapsedData);
+ },
+ },
+ watch: {
+ isCollapsed(newVal) {
+ if (!newVal) {
+ this.loadAllData();
+ } else {
+ this.loadingState = null;
+ }
+ },
+ },
+ mounted() {
+ this.fetchCollapsedData(this.$props)
+ .then(data => {
+ this.collapsedData = data;
+ this.loadingState = null;
+ })
+ .catch(e => {
+ this.loadingState = LOADING_STATES.collapsedError;
+ throw e;
+ });
+ },
+ methods: {
+ toggleCollapsed() {
+ this.isCollapsed = !this.isCollapsed;
+ },
+ loadAllData() {
+ if (this.fullData) return;
+
+ this.loadingState = LOADING_STATES.expandedLoading;
+
+ this.fetchFullData(this.$props)
+ .then(data => {
+ this.loadingState = null;
+ this.fullData = data;
+ })
+ .catch(e => {
+ this.loadingState = null;
+ throw e;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <section class="media-section mr-widget-border-top">
+ <div class="media gl-p-5">
+ <status-icon :status="statusIconName" class="align-self-center" />
+ <div class="media-body d-flex flex-align-self-center align-items-center">
+ <div class="code-text">
+ <template v-if="isLoadingSummary">
+ {{ __('Loading...') }}
+ </template>
+ <div v-else v-safe-html="summary(collapsedData)"></div>
+ </div>
+ <gl-button
+ v-if="isCollapsible"
+ size="small"
+ class="float-right align-self-center"
+ @click="toggleCollapsed"
+ >
+ {{ isCollapsed ? __('Expand') : __('Collapse') }}
+ </gl-button>
+ </div>
+ </div>
+ <div v-if="!isCollapsed" class="mr-widget-grouped-section">
+ <div v-if="isLoadingExpanded" class="report-block-container">
+ <gl-loading-icon inline /> {{ __('Loading...') }}
+ </div>
+ <smart-virtual-list
+ v-else-if="fullData"
+ :length="fullData.length"
+ :remain="20"
+ :size="32"
+ wtag="ul"
+ wclass="report-block-list"
+ class="report-block-container"
+ >
+ <li v-for="data in fullData" :key="data.id" class="d-flex align-items-center">
+ <div v-if="data.icon" :class="data.icon.class" class="d-flex">
+ <gl-icon :name="data.icon.name" :size="24" />
+ </div>
+ <div
+ class="gl-mt-2 gl-mb-2 align-content-around align-items-start flex-wrap align-self-center d-flex"
+ >
+ <div class="gl-mr-4">
+ {{ data.text }}
+ </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>
+ </div>
+ </li>
+ </smart-virtual-list>
+ </div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
new file mode 100644
index 00000000000..5014c12dc30
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/container.js
@@ -0,0 +1,27 @@
+import { extensions } from './index';
+
+export default {
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ },
+ render(h) {
+ return h(
+ 'div',
+ {},
+ extensions.map(extension =>
+ h(extension, {
+ props: extensions[0].props.reduce(
+ (acc, key) => ({
+ ...acc,
+ [key]: this.mr[key],
+ }),
+ {},
+ ),
+ }),
+ ),
+ );
+ },
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
new file mode 100644
index 00000000000..2bfaec8a1c9
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/index.js
@@ -0,0 +1,30 @@
+import ExtensionBase from './base.vue';
+
+// Holds all the currently registered extensions
+export const extensions = [];
+
+export const registerExtension = extension => {
+ // Pushes into the extenions array a dynamically created Vue component
+ // that gets exteneded from `base.vue`
+ extensions.push({
+ extends: ExtensionBase,
+ name: extension.name,
+ props: extension.props,
+ computed: {
+ ...Object.keys(extension.computed).reduce(
+ (acc, computedKey) => ({
+ ...acc,
+ // Making the computed property a method allows us to pass in arguments
+ // this allows for each computed property to recieve some data
+ [computedKey]() {
+ return extension.computed[computedKey];
+ },
+ }),
+ {},
+ ),
+ },
+ methods: {
+ ...extension.methods,
+ },
+ });
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
index 598b08f4c16..5ed699acddf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
@@ -1,10 +1,10 @@
<script>
-import tooltip from '../../vue_shared/directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
export default {
name: 'MrWidgetAuthor',
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
author: {
@@ -16,11 +16,6 @@ export default {
required: false,
default: true,
},
- showAuthorTooltip: {
- type: Boolean,
- required: false,
- default: false,
- },
},
computed: {
authorUrl() {
@@ -33,12 +28,7 @@ export default {
};
</script>
<template>
- <a
- :href="authorUrl"
- :v-tooltip="showAuthorTooltip"
- :title="author.name"
- class="author-link inline"
- >
+ <a v-gl-tooltip :href="authorUrl" :title="author.name" class="author-link inline">
<img :src="avatarUrl" class="avatar avatar-inline s16" />
<span v-if="showAuthorName" class="author">{{ author.name }}</span>
</a>
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 eb8989adb2a..d5fdbe726e9 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
@@ -1,6 +1,5 @@
<script>
/* eslint-disable vue/no-v-html */
-import Mousetrap from 'mousetrap';
import { escape } from 'lodash';
import {
GlButton,
@@ -84,17 +83,6 @@ export default {
: '';
},
},
- mounted() {
- Mousetrap.bind('b', this.copyBranchName);
- },
- beforeDestroy() {
- Mousetrap.unbind('b');
- },
- methods: {
- copyBranchName() {
- this.$refs.copyBranchNameButton.$el.click();
- },
- },
};
</script>
<template>
@@ -110,7 +98,6 @@ export default {
class="label-branch label-truncate js-source-branch"
v-html="mr.sourceBranchLink"
/><clipboard-button
- ref="copyBranchNameButton"
data-testid="mr-widget-copy-clipboard"
:text="branchNameClipboardData"
:title="__('Copy branch name')"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
index f17e409d996..b6722de5277 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_message_dropdown.vue
@@ -1,10 +1,10 @@
<script>
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
export default {
components: {
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
},
props: {
commits: {
@@ -18,20 +18,20 @@ export default {
<template>
<div>
- <gl-deprecated-dropdown
+ <gl-dropdown
right
text="Use an existing commit message"
variant="link"
class="mr-commit-dropdown"
>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-for="commit in commits"
:key="commit.short_id"
class="text-nowrap text-truncate"
@click="$emit('input', commit.message)"
>
<span class="monospace mr-2">{{ commit.short_id }}</span> {{ commit.title }}
- </gl-deprecated-dropdown-item>
- </gl-deprecated-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</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 12f65a4c235..750014c599a 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,4 +1,5 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import autoMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/auto_merge';
import { deprecatedCreateFlash as Flash } from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -12,6 +13,7 @@ export default {
components: {
MrWidgetAuthor,
statusIcon,
+ GlLoadingIcon,
},
mixins: [autoMergeMixin],
props: {
@@ -100,7 +102,7 @@ export default {
class="btn btn-sm btn-default js-cancel-auto-merge"
@click.prevent="cancelAutomaticMerge"
>
- <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ <gl-loading-icon v-if="isCancellingAutoMerge" inline class="gl-mr-1" />
{{ cancelButtonText }}
</a>
</h4>
@@ -122,7 +124,7 @@ export default {
href="#"
@click.prevent="removeSourceBranch"
>
- <i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ <gl-loading-icon v-if="isRemovingSourceBranch" inline class="gl-mr-1" />
{{ s__('mrWidget|Delete source branch') }}
</a>
</p>
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 835f7b9e9a9..2c1f2285dda 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
@@ -1,6 +1,15 @@
<script>
import { isEmpty } from 'lodash';
-import { GlIcon, GlButton, GlSprintf, GlLink } from '@gitlab/ui';
+import {
+ GlIcon,
+ GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
+ GlSprintf,
+ GlLink,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
import simplePoll from '~/lib/utils/simple_poll';
import { __ } from '~/locale';
@@ -36,6 +45,9 @@ export default {
GlSprintf,
GlLink,
GlButton,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
MergeTrainHelperText: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_text.vue'),
MergeImmediatelyConfirmationDialog: () =>
@@ -43,6 +55,9 @@ export default {
'ee_component/vue_merge_request_widget/components/merge_immediately_confirmation_dialog.vue'
),
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
mixins: [readyToMergeMixin],
props: {
mr: { type: Object, required: true },
@@ -283,7 +298,7 @@ export default {
<status-icon :status="iconClass" />
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
- <span class="btn-group">
+ <gl-button-group>
<gl-button
size="medium"
category="primary"
@@ -294,54 +309,33 @@ export default {
@click="handleMergeButtonClick(isAutoMergeAvailable)"
>{{ mergeButtonText }}</gl-button
>
- <button
+ <gl-dropdown
v-if="shouldShowMergeImmediatelyDropdown"
+ v-gl-tooltip.hover.focus="__('Select merge moment')"
:disabled="isMergeButtonDisabled"
- type="button"
- class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
- data-toggle="dropdown"
+ variant="info"
data-qa-selector="merge_moment_dropdown"
- :aria-label="__('Select merge moment')"
- >
- <i class="fa fa-chevron-down" aria-hidden="true"></i>
- </button>
- <ul
- v-if="shouldShowMergeImmediatelyDropdown"
- class="dropdown-menu dropdown-menu-right"
- role="menu"
+ toggle-class="btn-icon js-merge-moment"
>
- <li>
- <a
- class="auto_merge_enabled qa-merge-when-pipeline-succeeds-option"
- href="#"
- @click.prevent="handleMergeButtonClick(true)"
- >
- <span class="media">
- <gl-icon name="status_success" class="merge-opt-icon" aria-hidden="true" />
- <span class="media-body merge-opt-title">{{ autoMergeText }}</span>
- </span>
- </a>
- </li>
- <li>
- <merge-immediately-confirmation-dialog
- ref="confirmationDialog"
- :docs-url="mr.mergeImmediatelyDocsPath"
- @mergeImmediately="onMergeImmediatelyConfirmation"
- />
- <a
- class="accept-merge-request js-merge-immediately-button"
- data-qa-selector="merge_immediately_option"
- href="#"
- @click.prevent="handleMergeImmediatelyButtonClick"
- >
- <span class="media">
- <gl-icon name="status_warning" class="merge-opt-icon" aria-hidden="true" />
- <span class="media-body merge-opt-title">{{ __('Merge immediately') }}</span>
- </span>
- </a>
- </li>
- </ul>
- </span>
+ <template #button-content>
+ <gl-icon name="chevron-down" class="mr-0" />
+ <span class="sr-only">{{ __('Select merge moment') }}</span>
+ </template>
+ <gl-dropdown-item
+ icon-name="warning"
+ button-class="accept-merge-request js-merge-immediately-button"
+ data-qa-selector="merge_immediately_option"
+ @click="handleMergeImmediatelyButtonClick"
+ >
+ {{ __('Merge immediately') }}
+ </gl-dropdown-item>
+ <merge-immediately-confirmation-dialog
+ ref="confirmationDialog"
+ :docs-url="mr.mergeImmediatelyDocsPath"
+ @mergeImmediately="onMergeImmediatelyConfirmation"
+ />
+ </gl-dropdown>
+ </gl-button-group>
<div class="media-body-wrap space-children">
<template v-if="shouldShowMergeControls">
<label v-if="mr.canRemoveSourceBranch">
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 eba3d50fdc9..1d591168a17 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
@@ -1,6 +1,7 @@
<script>
import $ from 'jquery';
import { GlButton } from '@gitlab/ui';
+import { produce } from 'immer';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import MergeRequest from '~/merge_request';
@@ -80,12 +81,18 @@ export default {
return;
}
- const data = store.readQuery({
+ const sourceData = store.readQuery({
query: getStateQuery,
variables: mergeRequestQueryVariables,
});
- data.project.mergeRequest.workInProgress = workInProgress;
- data.project.mergeRequest.title = title;
+
+ const data = produce(sourceData, draftState => {
+ // eslint-disable-next-line no-param-reassign
+ draftState.project.mergeRequest.workInProgress = workInProgress;
+ // eslint-disable-next-line no-param-reassign
+ draftState.project.mergeRequest.title = title;
+ });
+
store.writeQuery({
query: getStateQuery,
data,
@@ -143,7 +150,7 @@ export default {
<div class="media-body">
<div class="gl-ml-3 float-left">
<span class="gl-font-weight-bold">
- {{ __('This merge request is still a work in progress.') }}
+ {{ __('This merge request is still a draft.') }}
</span>
<span class="gl-display-block text-muted">{{
__("Draft merge requests can't be merged.")
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
new file mode 100644
index 00000000000..2d21ced1b28
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -0,0 +1,66 @@
+/* eslint-disable */
+import issuesCollapsedQuery from './issues_collapsed.query.graphql';
+import issuesQuery from './issues.query.graphql';
+
+export default {
+ // Give the extension a name
+ // Make it easier to track in Vue dev tools
+ name: 'WidgetIssues',
+ // Add an array of props
+ // These then get mapped to values stored in the MR Widget store
+ props: ['targetProjectFullPath'],
+ // Add any extra computed props in here
+ computed: {
+ // Small summary text to be displayed in the collapsed state
+ // Receives the collapsed data as an argument
+ summary(count) {
+ return `<strong>${count}</strong> open issue`;
+ },
+ // Status icon to be used next to the summary text
+ // Receives the collapsed data as an argument
+ statusIcon(count) {
+ return count > 0 ? 'warning' : 'success';
+ },
+ },
+ methods: {
+ // Fetches the collapsed data
+ // Ideally, this request should return the smallest amount of data possible
+ // Receives an object of all the props passed in to the extension
+ fetchCollapsedData({ targetProjectFullPath }) {
+ return this.$apollo
+ .query({ query: issuesCollapsedQuery, variables: { projectPath: targetProjectFullPath } })
+ .then(({ data }) => data.project.issues.count);
+ },
+ // Fetches the full data when the extension is expanded
+ // Receives an object of all the props passed in to the extension
+ fetchFullData({ targetProjectFullPath }) {
+ return this.$apollo
+ .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 => ({
+ id: issue.id, // Required: The ID of the object
+ text: issue.title, // Required: The text to get used on each row
+ // Icon to get rendered on the side of each row
+ icon: {
+ // Required: Name maps to an icon in GitLabs SVG
+ name:
+ issue.state === 'closed' ? 'status_failed_borderless' : 'status_success_borderless',
+ // Optional: An extra class to be added to the icon for additional styling
+ class: issue.state === 'closed' ? 'text-danger' : 'text-success',
+ },
+ // Badges get rendered next to the text on each row
+ badge: issue.state === 'closed' && {
+ text: 'Closed', // Required: Text to be used inside of the badge
+ // variant: 'info', // Optional: The variant of the badge, maps to GitLab UI variants
+ },
+ // Each row can have its own link that will take the user elsewhere
+ // link: {
+ // href: 'https://google.com', // Required: href for the link
+ // text: 'Link text', // Required: Text to be used inside the link
+ // },
+ }));
+ });
+ },
+ },
+};
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
new file mode 100644
index 00000000000..690f571c083
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql
@@ -0,0 +1,13 @@
+query getAllIssues($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ issues {
+ nodes {
+ id
+ title
+ webPath
+ webUrl
+ state
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000000..389a81e0a61
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
@@ -0,0 +1,7 @@
+query getIssues($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ issues {
+ count
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index 87e56dfcbdf..8f2cca3309a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -3,12 +3,19 @@ import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_optio
import VueApollo from 'vue-apollo';
import Translate from '../vue_shared/translate';
import createDefaultClient from '~/lib/graphql';
+import { registerExtension } from './components/extensions';
+import issueExtension from './extensions/issues';
Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
+ defaultClient: createDefaultClient(
+ {},
+ {
+ assumeImmutableResults: true,
+ },
+ ),
});
export default () => {
@@ -17,6 +24,8 @@ export default () => {
gl.mrWidgetData.gitlabLogo = gon.gitlab_logo;
gl.mrWidgetData.defaultAvatarUrl = gon.default_avatar_url;
+ registerExtension(issueExtension);
+
const vm = new Vue({ ...MrWidgetOptions, apolloProvider });
window.gl.mrWidget = {
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 46749fc5e87..190d790f584 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
@@ -37,6 +37,7 @@ import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
import MrWidgetAutoMergeEnabled from './components/states/mr_widget_auto_merge_enabled.vue';
import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
import CheckingState from './components/states/mr_widget_checking.vue';
+// import ExtensionsContainer from './components/extensions/container';
import eventHub from './event_hub';
import notify from '~/lib/utils/notify';
import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
@@ -46,7 +47,6 @@ import GroupedTestReportsApp from '../reports/components/grouped_test_reports_ap
import { setFaviconOverlay } from '../lib/utils/common_utils';
import GroupedAccessibilityReportsApp from '../reports/accessibility_report/grouped_accessibility_reports_app.vue';
import getStateQuery from './queries/get_state.query.graphql';
-import { isExperimentEnabled } from '~/lib/utils/experimentation';
export default {
el: '#js-vue-mr-widget',
@@ -58,6 +58,7 @@ export default {
},
components: {
Loading,
+ // ExtensionsContainer,
'mr-widget-header': WidgetHeader,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
'mr-widget-merge-help': WidgetMergeHelp,
@@ -154,7 +155,7 @@ export default {
},
shouldSuggestPipelines() {
return (
- isExperimentEnabled('suggestPipeline') &&
+ gon.features?.suggestPipeline &&
!this.mr.hasCI &&
this.mr.mergeRequestAddCiConfigPath &&
!this.mr.isDismissedSuggestPipeline
@@ -455,6 +456,7 @@ export default {
:service="service"
/>
<div class="mr-section-container mr-widget-workflow">
+ <!-- <extensions-container :mr="mr" /> -->
<grouped-codequality-reports-app
v-if="shouldRenderCodeQuality"
:base-path="mr.codeclimate.base_path"