diff options
Diffstat (limited to 'app/assets/javascripts/work_items/components/work_item_state_toggle.vue')
-rw-r--r-- | app/assets/javascripts/work_items/components/work_item_state_toggle.vue | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/app/assets/javascripts/work_items/components/work_item_state_toggle.vue b/app/assets/javascripts/work_items/components/work_item_state_toggle.vue new file mode 100644 index 00000000000..581ef9ec945 --- /dev/null +++ b/app/assets/javascripts/work_items/components/work_item_state_toggle.vue @@ -0,0 +1,131 @@ +<script> +import { GlButton, GlDisclosureDropdownItem, GlLoadingIcon } from '@gitlab/ui'; +import * as Sentry from '~/sentry/sentry_browser_wrapper'; +import Tracking from '~/tracking'; +import { __ } from '~/locale'; +import { getUpdateWorkItemMutation } from '~/work_items/components/update_work_item'; +import { + sprintfWorkItem, + I18N_WORK_ITEM_ERROR_UPDATING, + STATE_OPEN, + STATE_EVENT_CLOSE, + STATE_EVENT_REOPEN, + TRACKING_CATEGORY_SHOW, +} from '../constants'; + +export default { + components: { + GlButton, + GlDisclosureDropdownItem, + GlLoadingIcon, + }, + mixins: [Tracking.mixin()], + props: { + workItemState: { + type: String, + required: true, + }, + workItemId: { + type: String, + required: true, + }, + workItemType: { + type: String, + required: true, + }, + workItemParentId: { + type: String, + required: false, + default: null, + }, + showAsDropdownItem: { + type: Boolean, + required: false, + default: false, + }, + }, + data() { + return { + updateInProgress: false, + }; + }, + computed: { + isWorkItemOpen() { + return this.workItemState === STATE_OPEN; + }, + toggleWorkItemStateText() { + const baseText = this.isWorkItemOpen + ? __('Close %{workItemType}') + : __('Reopen %{workItemType}'); + return sprintfWorkItem(baseText, this.workItemType); + }, + tracking() { + return { + category: TRACKING_CATEGORY_SHOW, + label: 'item_state', + property: `type_${this.workItemType}`, + }; + }, + toggleInProgressText() { + const baseText = this.isWorkItemOpen + ? __('Closing %{workItemType}') + : __('Reopening %{workItemType}'); + return sprintfWorkItem(baseText, this.workItemType); + }, + }, + methods: { + async updateWorkItem() { + const input = { + id: this.workItemId, + stateEvent: this.isWorkItemOpen ? STATE_EVENT_CLOSE : STATE_EVENT_REOPEN, + }; + + this.updateInProgress = true; + + try { + this.track('updated_state'); + + const { mutation, variables } = getUpdateWorkItemMutation({ + workItemParentId: this.workItemParentId, + input, + }); + + const { data } = await this.$apollo.mutate({ + mutation, + variables, + }); + + const errors = data.workItemUpdate?.errors; + + if (errors?.length) { + throw new Error(errors[0]); + } + } catch (error) { + const msg = sprintfWorkItem(I18N_WORK_ITEM_ERROR_UPDATING, this.workItemType); + + this.$emit('error', msg); + Sentry.captureException(error); + } + + this.updateInProgress = false; + }, + }, +}; +</script> + +<template> + <gl-disclosure-dropdown-item v-if="showAsDropdownItem" @action="updateWorkItem"> + <template #list-item> + <template v-if="updateInProgress"> + <gl-loading-icon inline size="sm" /> + {{ toggleInProgressText }} + </template> + <template v-else> + {{ toggleWorkItemStateText }} + </template> + </template> + </gl-disclosure-dropdown-item> + <gl-button v-else :loading="updateInProgress" @click="updateWorkItem">{{ + toggleWorkItemStateText + }}</gl-button> +</template> |