diff options
Diffstat (limited to 'app/assets/javascripts/related_issues/components/related_issues_list.vue')
-rw-r--r-- | app/assets/javascripts/related_issues/components/related_issues_list.vue | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue new file mode 100644 index 00000000000..a75fe4397bb --- /dev/null +++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue @@ -0,0 +1,146 @@ +<script> +import { GlLoadingIcon } from '@gitlab/ui'; +import Sortable from 'sortablejs'; +import sortableConfig from 'ee_else_ce/sortable/sortable_config'; +import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue'; +import tooltip from '~/vue_shared/directives/tooltip'; + +export default { + name: 'RelatedIssuesList', + directives: { + tooltip, + }, + components: { + GlLoadingIcon, + RelatedIssuableItem, + }, + props: { + canAdmin: { + type: Boolean, + required: false, + default: false, + }, + canReorder: { + type: Boolean, + required: false, + default: false, + }, + heading: { + type: String, + required: false, + default: '', + }, + isFetching: { + type: Boolean, + required: false, + default: false, + }, + issuableType: { + type: String, + required: true, + }, + pathIdSeparator: { + type: String, + required: true, + }, + relatedIssues: { + type: Array, + required: false, + default: () => [], + }, + }, + mounted() { + if (this.canReorder) { + this.sortable = Sortable.create(this.$refs.list, { + ...sortableConfig, + onStart: this.addDraggingCursor, + onEnd: this.reordered, + }); + } + }, + methods: { + getBeforeAfterId(itemEl) { + const prevItemEl = itemEl.previousElementSibling; + const nextItemEl = itemEl.nextElementSibling; + + return { + beforeId: prevItemEl && parseInt(prevItemEl.dataset.orderingId, 0), + afterId: nextItemEl && parseInt(nextItemEl.dataset.orderingId, 0), + }; + }, + reordered(event) { + this.removeDraggingCursor(); + const { beforeId, afterId } = this.getBeforeAfterId(event.item); + const { oldIndex, newIndex } = event; + + this.$emit('saveReorder', { + issueId: parseInt(event.item.dataset.key, 10), + oldIndex, + newIndex, + afterId, + beforeId, + }); + }, + addDraggingCursor() { + document.body.classList.add('is-dragging'); + }, + removeDraggingCursor() { + document.body.classList.remove('is-dragging'); + }, + issuableOrderingId({ epicIssueId, id }) { + return this.issuableType === 'issue' ? epicIssueId : id; + }, + }, +}; +</script> + +<template> + <div> + <h4 v-if="heading" class="gl-font-base mt-0">{{ heading }}</h4> + <div + class="related-issues-token-body bordered-box bg-white" + :class="{ 'sortable-container': canReorder }" + > + <div v-if="isFetching" class="related-issues-loading-icon qa-related-issues-loading-icon"> + <gl-loading-icon ref="loadingIcon" label="Fetching linked issues" class="gl-mt-2" /> + </div> + <ul ref="list" :class="{ 'content-list': !canReorder }" class="related-items-list"> + <li + v-for="issue in relatedIssues" + :key="issue.id" + :class="{ + 'user-can-drag': canReorder, + 'sortable-row': canReorder, + 'card card-slim': canReorder, + }" + :data-key="issue.id" + :data-ordering-id="issuableOrderingId(issue)" + class="js-related-issues-token-list-item list-item pt-0 pb-0" + > + <related-issuable-item + :id-key="issue.id" + :display-reference="issue.reference" + :confidential="issue.confidential" + :title="issue.title" + :path="issue.path" + :state="issue.state" + :milestone="issue.milestone" + :assignees="issue.assignees" + :created-at="issue.createdAt" + :closed-at="issue.closedAt" + :weight="issue.weight" + :due-date="issue.dueDate" + :can-remove="canAdmin" + :can-reorder="canReorder" + :path-id-separator="pathIdSeparator" + :is-locked="issue.lockIssueRemoval" + :locked-message="issue.lockedMessage" + event-namespace="relatedIssue" + class="qa-related-issuable-item" + @relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)" + /> + </li> + </ul> + </div> + </div> +</template> |