Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/mr_more_dropdown.vue')
-rw-r--r--app/assets/javascripts/vue_shared/components/mr_more_dropdown.vue361
1 files changed, 361 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/mr_more_dropdown.vue b/app/assets/javascripts/vue_shared/components/mr_more_dropdown.vue
new file mode 100644
index 00000000000..064458cfc1f
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/mr_more_dropdown.vue
@@ -0,0 +1,361 @@
+<script>
+import {
+ GlLoadingIcon,
+ GlButton,
+ GlIcon,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
+ GlDisclosureDropdownGroup,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { apolloProvider } from '~/graphql_shared/issuable_client';
+import { __, s__ } from '~/locale';
+import api from '~/api';
+import axios from '~/lib/utils/axios_utils';
+import { createAlert } from '~/alert';
+import MergeRequest from '~/merge_request';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
+import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue';
+import NewHeaderActionsPopover from '~/issues/show/components/new_header_actions_popover.vue';
+import { TYPE_MERGE_REQUEST } from '~/issues/constants';
+
+Vue.use(VueApollo);
+
+export default {
+ apolloProvider,
+ i18n: {
+ edit: __('Edit'),
+ copyReferenceText: __('Copy reference'),
+ errorMessage: __('Something went wrong. Please try again.'),
+ issuableName: __('merge request'),
+ reportAbuse: __('Report abuse'),
+ markAsReady: __('Mark as ready'),
+ markAsDraft: __('Mark as draft'),
+ close: __('Close %{issuableType}'),
+ closing: __('Closing %{issuableType}...'),
+ reopen: __('Reopen %{issuableType}'),
+ reopening: __('Reopening %{issuableType}...'),
+ lock: __('Lock %{issuableType}'),
+ mergeRequestActions: __('Merge request actions'),
+ },
+ components: {
+ GlLoadingIcon,
+ GlButton,
+ GlIcon,
+ GlDisclosureDropdown,
+ GlDisclosureDropdownItem,
+ GlDisclosureDropdownGroup,
+ SidebarSubscriptionsWidget,
+ AbuseCategorySelector,
+ NewHeaderActionsPopover,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [glFeatureFlagMixin()],
+ inject: {
+ reportAbusePath: {
+ default: '',
+ },
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ editUrl: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ isCurrentUser: {
+ type: Boolean,
+ default: false,
+ required: true,
+ },
+ isLoggedIn: {
+ type: Boolean,
+ defauilt: false,
+ required: false,
+ },
+ canUpdateMergeRequest: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ open: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ isMerged: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ sourceProjectMissing: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ clipboardText: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ reportedUserId: {
+ type: Number,
+ default: 0,
+ required: false,
+ },
+ reportedFromUrl: {
+ type: String,
+ default: '',
+ required: false,
+ },
+ },
+ data() {
+ return {
+ isOpen: this.open,
+ draft: this.mr.draft,
+ issuableType: TYPE_MERGE_REQUEST,
+ fullPath: this.projectPath,
+ isLoading: false,
+ isLoadingDraft: false,
+ isLoadingClipboard: false,
+ isReportAbuseDrawerOpen: false,
+ };
+ },
+ computed: {
+ isMovedMrSidebar() {
+ return this.glFeatures.movedMrSidebar;
+ },
+ draftLabel() {
+ return this.draft ? this.$options.i18n.markAsReady : this.$options.i18n.markAsDraft;
+ },
+ draftState() {
+ return this.draft ? 'ready' : 'draft';
+ },
+ editItem() {
+ return {
+ text: this.$options.i18n.edit,
+ href: this.editUrl,
+ };
+ },
+ },
+ methods: {
+ draftAction() {
+ this.isLoadingDraft = true;
+
+ axios
+ .put(`?merge_request[wip_event]=${this.draftState}`, null, {
+ params: { format: 'json' },
+ })
+ .then(({ data }) => {
+ MergeRequest.toggleDraftStatus(data.title, this.draft);
+ })
+ .catch(() => {
+ createAlert({
+ message: this.$options.i18n.errorMessage,
+ });
+ })
+ .finally(() => {
+ this.draft = !this.draft;
+ this.isLoadingDraft = false;
+ this.closeActionsDropdown();
+ });
+ },
+ stateAction(state) {
+ this.isLoading = true;
+
+ api
+ .updateMergeRequest(this.mr.target_project_id, this.mr.iid, { state_event: state })
+ .then(() => {
+ window.location.reload();
+ })
+ .catch(() => {
+ createAlert({
+ message: this.$options.i18n.errorMessage,
+ });
+ })
+ .finally(() => {
+ this.isOpen = !this.isOpen;
+ this.isLoading = false;
+ this.closeActionsDropdown();
+ });
+ },
+ copyClipboardAction() {
+ this.$toast.show(s__('MergeRequests|Reference copied'));
+ this.closeActionsDropdown();
+ },
+ reportAbuseAction(isOpen) {
+ if (isOpen) {
+ this.closeActionsDropdown();
+ }
+
+ this.isReportAbuseDrawerOpen = isOpen;
+ },
+ closeActionsDropdown() {
+ this.$refs.mrMoreActionsDropdown.close();
+ },
+ showReopenMergeRequestOption() {
+ return !this.sourceProjectMissing && !this.isOpen;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-display-flex gl-justify-content-end gl-w-full gl-relative"
+ data-testid="merge-request-actions"
+ >
+ <gl-disclosure-dropdown
+ id="new-actions-header-dropdown"
+ ref="mrMoreActionsDropdown"
+ data-testid="dropdown-toggle"
+ placement="right"
+ :auto-close="false"
+ >
+ <template #toggle>
+ <div class="gl-min-h-7 gl-mb-2 gl-md-mb-0!" :aria-label="$options.i18n.mergeRequestActions">
+ <gl-button
+ class="gl-md-display-none! gl-new-dropdown-toggle gl-absolute gl-top-0 gl-left-0 gl-w-full"
+ category="secondary"
+ >
+ <span class="">{{ $options.i18n.mergeRequestActions }}</span>
+ <gl-icon class="dropdown-chevron" name="chevron-down" />
+ </gl-button>
+ <gl-button
+ class="gl-display-none gl-md-display-flex! gl-new-dropdown-toggle gl-new-dropdown-icon-only gl-new-dropdown-toggle-no-caret gl-ml-3"
+ category="tertiary"
+ icon="ellipsis_v"
+ />
+ </div>
+ </template>
+ <gl-disclosure-dropdown-group v-if="isLoggedIn && isMovedMrSidebar">
+ <sidebar-subscriptions-widget
+ :iid="String(mr.iid)"
+ :full-path="fullPath"
+ :issuable-type="issuableType"
+ data-testid="notification-toggle"
+ />
+ </gl-disclosure-dropdown-group>
+
+ <gl-disclosure-dropdown-group
+ bordered
+ :class="{ 'gl-mt-0! gl-pt-0! gl-border-t-0!': !(isLoggedIn && isMovedMrSidebar) }"
+ >
+ <gl-disclosure-dropdown-item
+ v-if="canUpdateMergeRequest"
+ class="gl-md-display-none!"
+ data-testid="edit-merge-request"
+ :item="editItem"
+ />
+
+ <gl-disclosure-dropdown-item
+ v-if="isOpen && canUpdateMergeRequest"
+ data-testid="ready-and-draft-action"
+ @action="draftAction"
+ >
+ <template #list-item>
+ <gl-loading-icon v-if="isLoadingDraft" inline size="sm" />
+ {{ draftLabel }}
+ </template>
+ </gl-disclosure-dropdown-item>
+
+ <gl-disclosure-dropdown-item
+ v-if="isOpen && canUpdateMergeRequest"
+ data-testid="close-merge-request"
+ @action="stateAction('close')"
+ >
+ <template #list-item>
+ <template v-if="isLoading">
+ <gl-loading-icon inline size="sm" />
+ {{
+ sprintf($options.i18n.closing, {
+ issuableType: $options.i18n.issuableName,
+ })
+ }}
+ </template>
+ <template v-else>
+ {{ sprintf($options.i18n.close, { issuableType: $options.i18n.issuableName }) }}
+ </template>
+ </template>
+ </gl-disclosure-dropdown-item>
+
+ <gl-disclosure-dropdown-item
+ v-else-if="!isMerged && showReopenMergeRequestOption && canUpdateMergeRequest"
+ data-testid="reopen-merge-request"
+ @action="stateAction('reopen')"
+ >
+ <template #list-item>
+ <template v-if="isLoading">
+ <gl-loading-icon inline size="sm" />
+ {{
+ sprintf($options.i18n.reopening, {
+ issuableType: $options.i18n.issuableName,
+ })
+ }}
+ </template>
+ <template v-else>
+ {{ sprintf($options.i18n.reopen, { issuableType: $options.i18n.issuableName }) }}
+ </template>
+ </template>
+ </gl-disclosure-dropdown-item>
+
+ <gl-disclosure-dropdown-item v-if="isMovedMrSidebar" class="js-sidebar-lock-root">
+ <template #list-item>
+ {{ sprintf($options.i18n.lock, { issuableType: $options.i18n.issuableName }) }}
+ </template>
+ </gl-disclosure-dropdown-item>
+
+ <gl-disclosure-dropdown-item
+ v-if="isMovedMrSidebar"
+ class="js-copy-reference"
+ :data-clipboard-text="clipboardText"
+ data-testid="copy-reference"
+ @action="copyClipboardAction"
+ >
+ <template #list-item>
+ {{ $options.i18n.copyReferenceText }}
+ </template>
+ </gl-disclosure-dropdown-item>
+ </gl-disclosure-dropdown-group>
+
+ <gl-disclosure-dropdown-group
+ v-if="!isCurrentUser"
+ bordered
+ :class="{ 'gl-mt-0! gl-pt-0! gl-border-t-0!': !canUpdateMergeRequest }"
+ >
+ <gl-disclosure-dropdown-item
+ class="js-report-abuse-dropdown-item"
+ data-testid="report-abuse-option"
+ @action="reportAbuseAction(true)"
+ >
+ <template #list-item>
+ {{ $options.i18n.reportAbuse }}
+ </template>
+ </gl-disclosure-dropdown-item>
+ </gl-disclosure-dropdown-group>
+ </gl-disclosure-dropdown>
+
+ <new-header-actions-popover v-if="isMovedMrSidebar" :issue-type="issuableType" />
+
+ <abuse-category-selector
+ v-if="!isCurrentUser && isReportAbuseDrawerOpen"
+ :reported-user-id="reportedUserId"
+ :reported-from-url="reportedFromUrl"
+ :show-drawer="isReportAbuseDrawerOpen"
+ @close-drawer="reportAbuseAction(false)"
+ />
+ </div>
+</template>