diff options
Diffstat (limited to 'app/assets/javascripts/issuable')
11 files changed, 83 insertions, 394 deletions
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/components/graphql/mutations/move_issue.mutation.graphql b/app/assets/javascripts/issuable/bulk_update_sidebar/components/graphql/mutations/move_issue.mutation.graphql deleted file mode 100644 index d350072425b..00000000000 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/components/graphql/mutations/move_issue.mutation.graphql +++ /dev/null @@ -1,5 +0,0 @@ -mutation moveIssue($moveIssueInput: IssueMoveInput!) { - issueMove(input: $moveIssueInput) { - errors - } -} diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/components/move_issues_button.vue b/app/assets/javascripts/issuable/bulk_update_sidebar/components/move_issues_button.vue deleted file mode 100644 index 6e287ac3bb7..00000000000 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/components/move_issues_button.vue +++ /dev/null @@ -1,171 +0,0 @@ -<script> -import { GlAlert } from '@gitlab/ui'; -import IssuableMoveDropdown from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue'; -import createFlash from '~/flash'; -import { logError } from '~/lib/logger'; -import { s__ } from '~/locale'; -import { - WORK_ITEM_TYPE_ENUM_ISSUE, - WORK_ITEM_TYPE_ENUM_INCIDENT, - WORK_ITEM_TYPE_ENUM_TASK, - WORK_ITEM_TYPE_ENUM_TEST_CASE, -} from '~/work_items/constants'; -import issuableEventHub from '~/issues/list/eventhub'; -import getIssuesQuery from 'ee_else_ce/issues/list/queries/get_issues.query.graphql'; -import getIssuesCountQuery from 'ee_else_ce/issues/list/queries/get_issues_counts.query.graphql'; -import moveIssueMutation from './graphql/mutations/move_issue.mutation.graphql'; - -export default { - name: 'MoveIssuesButton', - components: { - IssuableMoveDropdown, - GlAlert, - }, - props: { - projectFullPath: { - type: String, - required: true, - }, - projectsFetchPath: { - type: String, - required: true, - }, - }, - data() { - return { - selectedIssuables: [], - moveInProgress: false, - }; - }, - computed: { - cannotMoveTasksWarningTitle() { - if (this.tasksSelected && this.testCasesSelected) { - return s__('Issues|Tasks and test cases can not be moved.'); - } - - if (this.testCasesSelected) { - return s__('Issues|Test cases can not be moved.'); - } - - return s__('Issues|Tasks can not be moved.'); - }, - issuesSelected() { - return this.selectedIssuables.some((item) => item.type === WORK_ITEM_TYPE_ENUM_ISSUE); - }, - incidentsSelected() { - return this.selectedIssuables.some((item) => item.type === WORK_ITEM_TYPE_ENUM_INCIDENT); - }, - tasksSelected() { - return this.selectedIssuables.some((item) => item.type === WORK_ITEM_TYPE_ENUM_TASK); - }, - testCasesSelected() { - return this.selectedIssuables.some((item) => item.type === WORK_ITEM_TYPE_ENUM_TEST_CASE); - }, - }, - mounted() { - issuableEventHub.$on('issuables:issuableChecked', this.handleIssuableChecked); - }, - beforeDestroy() { - issuableEventHub.$off('issuables:issuableChecked', this.handleIssuableChecked); - }, - methods: { - handleIssuableChecked(issuable, value) { - if (value) { - this.selectedIssuables.push(issuable); - } else { - const index = this.selectedIssuables.indexOf(issuable); - if (index > -1) { - this.selectedIssuables.splice(index, 1); - } - } - }, - moveIssues(targetProject) { - const iids = this.selectedIssuables.reduce((result, issueData) => { - if ( - issueData.type === WORK_ITEM_TYPE_ENUM_ISSUE || - issueData.type === WORK_ITEM_TYPE_ENUM_INCIDENT - ) { - result.push(issueData.iid); - } - return result; - }, []); - - if (iids.length === 0) { - return; - } - - this.moveInProgress = true; - issuableEventHub.$emit('issuables:bulkMoveStarted'); - - const promises = iids.map((id) => { - return this.moveIssue(id, targetProject); - }); - - Promise.all(promises) - .then((promisesResult) => { - let foundError = false; - - for (const promiseResult of promisesResult) { - if (promiseResult.data.issueMove?.errors?.length) { - foundError = true; - logError( - `Error moving issue. Error message: ${promiseResult.data.issueMove.errors[0].message}`, - ); - } - } - - if (!foundError) { - const client = this.$apollo.provider.defaultClient; - client.refetchQueries({ - include: [getIssuesQuery, getIssuesCountQuery], - }); - this.moveInProgress = false; - this.selectedIssuables = []; - issuableEventHub.$emit('issuables:bulkMoveEnded'); - } else { - throw new Error(); - } - }) - .catch(() => { - this.moveInProgress = false; - issuableEventHub.$emit('issuables:bulkMoveEnded'); - - createFlash({ - message: s__(`Issues|There was an error while moving the issues.`), - }); - }); - }, - moveIssue(issueIid, targetProject) { - return this.$apollo.mutate({ - mutation: moveIssueMutation, - variables: { - moveIssueInput: { - projectPath: this.projectFullPath, - iid: issueIid, - targetProjectPath: targetProject.full_path, - }, - }, - }); - }, - }, - i18n: { - dropdownButtonTitle: s__('Issues|Move selected'), - }, -}; -</script> -<template> - <div> - <issuable-move-dropdown - :project-full-path="projectFullPath" - :projects-fetch-path="projectsFetchPath" - :move-in-progress="moveInProgress" - :disabled="!issuesSelected && !incidentsSelected" - :dropdown-header-title="$options.i18n.dropdownButtonTitle" - :dropdown-button-title="$options.i18n.dropdownButtonTitle" - @move-issuable="moveIssues" - /> - <gl-alert v-if="tasksSelected || testCasesSelected" :dismissible="false" variant="warning"> - {{ cannotMoveTasksWarningTitle }} - </gl-alert> - </div> -</template> diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue b/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue deleted file mode 100644 index ba94932289e..00000000000 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_dropdown.vue +++ /dev/null @@ -1,57 +0,0 @@ -<script> -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; -import { __ } from '~/locale'; -import { statusDropdownOptions } from '../constants'; - -export default { - components: { - GlDropdown, - GlDropdownItem, - }, - data() { - return { - status: null, - }; - }, - computed: { - dropdownText() { - return this.status?.text ?? this.$options.i18n.defaultDropdownText; - }, - selectedValue() { - return this.status?.value; - }, - }, - methods: { - onDropdownItemClick(statusOption) { - // clear status if the currently checked status is clicked again - if (this.status?.value === statusOption.value) { - this.status = null; - } else { - this.status = statusOption; - } - }, - }, - i18n: { - dropdownTitle: __('Change status'), - defaultDropdownText: __('Select status'), - }, - statusDropdownOptions, -}; -</script> -<template> - <div> - <input type="hidden" name="update[state_event]" :value="selectedValue" /> - <gl-dropdown :text="dropdownText" :title="$options.i18n.dropdownTitle" class="gl-w-full"> - <gl-dropdown-item - v-for="statusOption in $options.statusDropdownOptions" - :key="statusOption.value" - :is-checked="selectedValue === statusOption.value" - is-check-item - :title="statusOption.text" - @click="onDropdownItemClick(statusOption)" - > - {{ statusOption.text }} - </gl-dropdown-item> - </gl-dropdown> - </div> -</template> diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue b/app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue deleted file mode 100644 index 8774b065c22..00000000000 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue +++ /dev/null @@ -1,51 +0,0 @@ -<script> -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; -import { __ } from '~/locale'; -import { subscriptionsDropdownOptions } from '../constants'; - -export default { - subscriptionsDropdownOptions, - i18n: { - defaultDropdownText: __('Select subscription'), - headerText: __('Change subscription'), - }, - components: { - GlDropdown, - GlDropdownItem, - }, - data() { - return { - subscription: undefined, - }; - }, - computed: { - dropdownText() { - return this.subscription?.text ?? this.$options.i18n.defaultDropdownText; - }, - selectedValue() { - return this.subscription?.value; - }, - }, - methods: { - handleClick(option) { - this.subscription = option.value === this.subscription?.value ? undefined : option; - }, - }, -}; -</script> -<template> - <div> - <input type="hidden" name="update[subscription_event]" :value="selectedValue" /> - <gl-dropdown class="gl-w-full" :header-text="$options.i18n.headerText" :text="dropdownText"> - <gl-dropdown-item - v-for="subscriptionsOption in $options.subscriptionsDropdownOptions" - :key="subscriptionsOption.value" - is-check-item - :is-checked="selectedValue === subscriptionsOption.value" - @click="handleClick(subscriptionsOption)" - > - {{ subscriptionsOption.text }} - </gl-dropdown-item> - </gl-dropdown> - </div> -</template> diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js b/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js deleted file mode 100644 index 68133ceb3c7..00000000000 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js +++ /dev/null @@ -1,23 +0,0 @@ -import { __ } from '~/locale'; - -export const statusDropdownOptions = [ - { - text: __('Open'), - value: 'reopen', - }, - { - text: __('Closed'), - value: 'close', - }, -]; - -export const subscriptionsDropdownOptions = [ - { - text: __('Subscribe'), - value: 'subscribe', - }, - { - text: __('Unsubscribe'), - value: 'unsubscribe', - }, -]; diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/index.js b/app/assets/javascripts/issuable/bulk_update_sidebar/index.js deleted file mode 100644 index b7cb805ee37..00000000000 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/index.js +++ /dev/null @@ -1,75 +0,0 @@ -import Vue from 'vue'; -import VueApollo from 'vue-apollo'; -import { gqlClient } from '../../issues/list/graphql'; -import StatusDropdown from './components/status_dropdown.vue'; -import SubscriptionsDropdown from './components/subscriptions_dropdown.vue'; -import MoveIssuesButton from './components/move_issues_button.vue'; -import issuableBulkUpdateActions from './issuable_bulk_update_actions'; -import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar'; - -export function initBulkUpdateSidebar(prefixId) { - const el = document.querySelector('.issues-bulk-update'); - - if (!el) { - return; - } - - issuableBulkUpdateActions.init({ prefixId }); - new IssuableBulkUpdateSidebar(); // eslint-disable-line no-new -} - -export function initStatusDropdown() { - const el = document.querySelector('.js-status-dropdown'); - - if (!el) { - return null; - } - - return new Vue({ - el, - name: 'StatusDropdownRoot', - render: (createElement) => createElement(StatusDropdown), - }); -} - -export function initSubscriptionsDropdown() { - const el = document.querySelector('.js-subscriptions-dropdown'); - - if (!el) { - return null; - } - - return new Vue({ - el, - name: 'SubscriptionsDropdownRoot', - render: (createElement) => createElement(SubscriptionsDropdown), - }); -} - -export function initMoveIssuesButton() { - const el = document.querySelector('.js-move-issues'); - - if (!el) { - return null; - } - - const { dataset } = el; - - Vue.use(VueApollo); - const apolloProvider = new VueApollo({ - defaultClient: gqlClient, - }); - - return new Vue({ - el, - name: 'MoveIssuesRoot', - apolloProvider, - render: (createElement) => - createElement(MoveIssuesButton, { - props: { - projectFullPath: dataset.projectFullPath, - projectsFetchPath: dataset.projectsFetchPath, - }, - }), - }); -} diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue index 254248ef1d4..fd55f05e955 100644 --- a/app/assets/javascripts/issuable/components/related_issuable_item.vue +++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue @@ -1,13 +1,7 @@ <script> import '~/commons/bootstrap'; -import { - GlIcon, - GlLink, - GlTooltip, - GlTooltipDirective, - GlButton, - GlSafeHtmlDirective as SafeHtml, -} from '@gitlab/ui'; +import { GlIcon, GlLink, GlTooltip, GlTooltipDirective, GlButton } from '@gitlab/ui'; +import SafeHtml from '~/vue_shared/directives/safe_html'; import IssueDueDate from '~/boards/components/issue_due_date.vue'; import { TYPE_WORK_ITEM } from '~/graphql_shared/constants'; import { convertToGraphQLId } from '~/graphql_shared/utils'; diff --git a/app/assets/javascripts/issuable/index.js b/app/assets/javascripts/issuable/index.js index 10dbefce503..ed336deb2ed 100644 --- a/app/assets/javascripts/issuable/index.js +++ b/app/assets/javascripts/issuable/index.js @@ -1,12 +1,25 @@ import { GlToast } from '@gitlab/ui'; import Vue from 'vue'; -import IssuableContext from '~/issuable/issuable_context'; import { parseBoolean } from '~/lib/utils/common_utils'; import Sidebar from '~/right_sidebar'; import { getSidebarOptions } from '~/sidebar/mount_sidebar'; import CsvImportExportButtons from './components/csv_import_export_buttons.vue'; import IssuableByEmail from './components/issuable_by_email.vue'; import IssuableHeaderWarnings from './components/issuable_header_warnings.vue'; +import issuableBulkUpdateActions from './issuable_bulk_update_actions'; +import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar'; +import IssuableContext from './issuable_context'; + +export function initBulkUpdateSidebar(prefixId) { + const el = document.querySelector('.issues-bulk-update'); + + if (!el) { + return; + } + + issuableBulkUpdateActions.init({ prefixId }); + new IssuableBulkUpdateSidebar(); // eslint-disable-line no-new +} export function initCsvImportExportButtons() { const el = document.querySelector('.js-csv-import-export-buttons'); diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable/issuable_bulk_update_actions.js index 14824820c0d..c386267501a 100644 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js +++ b/app/assets/javascripts/issuable/issuable_bulk_update_actions.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import { difference, intersection, union } from 'lodash'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; @@ -32,7 +32,7 @@ export default { onFormSubmitFailure() { this.form.find('[type="submit"]').enable(); - return createFlash({ + return createAlert({ message: __('Issue update failed'), }); }, diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable/issuable_bulk_update_sidebar.js index b46a95c7dfa..095da60a583 100644 --- a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js +++ b/app/assets/javascripts/issuable/issuable_bulk_update_sidebar.js @@ -3,7 +3,12 @@ import $ from 'jquery'; import issuableEventHub from '~/issues/list/eventhub'; import LabelsSelect from '~/labels/labels_select'; -import { mountMilestoneDropdown } from '~/sidebar/mount_sidebar'; +import { + mountMilestoneDropdown, + mountMoveIssuesButton, + mountStatusDropdown, + mountSubscriptionsDropdown, +} from '~/sidebar/mount_sidebar'; import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; const HIDDEN_CLASS = 'hidden'; @@ -56,6 +61,9 @@ export default class IssuableBulkUpdateSidebar { initDropdowns() { new LabelsSelect(); mountMilestoneDropdown(); + mountMoveIssuesButton(); + mountStatusDropdown(); + mountSubscriptionsDropdown(); // Checking IS_EE and using ee_else_ce is odd, but we do it here to satisfy // the import/no-unresolved lint rule when FOSS_ONLY=1, even though at diff --git a/app/assets/javascripts/issuable/issuable_label_selector.js b/app/assets/javascripts/issuable/issuable_label_selector.js new file mode 100644 index 00000000000..ad8bbf04d6f --- /dev/null +++ b/app/assets/javascripts/issuable/issuable_label_selector.js @@ -0,0 +1,56 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import { + DropdownVariant, + LabelType, +} from '~/sidebar/components/labels/labels_select_widget/constants'; +import { WorkspaceType } from '~/issues/constants'; +import IssuableLabelSelector from '~/vue_shared/issuable/create/components/issuable_label_selector.vue'; + +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), +}); + +export default () => { + const el = document.querySelector('.js-issuable-form-label-selector'); + + if (!el) { + return false; + } + + const { + fieldName, + fullPath, + initialLabels, + issuableType, + labelsFilterBasePath, + labelsManagePath, + } = el.dataset; + + return new Vue({ + el, + apolloProvider, + provide: { + allowLabelCreate: true, + allowLabelEdit: true, + allowLabelRemove: true, + allowScopedLabels: true, + attrWorkspacePath: fullPath, + fieldName, + fullPath, + initialLabels: JSON.parse(initialLabels), + issuableType, + labelType: LabelType.project, + labelsFilterBasePath, + labelsManagePath, + variant: DropdownVariant.Embedded, + workspaceType: WorkspaceType.project, + }, + render(createElement) { + return createElement(IssuableLabelSelector); + }, + }); +}; |