gitlab-org--gitlab-foss/app/assets/javascripts/related_issues/components/related_issues_list.vue

148 lines
4.0 KiB
Vue

<script>
import { GlLoadingIcon } from '@gitlab/ui';
import Sortable from 'sortablejs';
import sortableConfig from '~/sortable/sortable_config';
import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
export default {
name: 'RelatedIssuesList',
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, 10),
afterId: nextItemEl && parseInt(nextItemEl.dataset.orderingId, 10),
};
},
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="gl-mb-2" data-qa-selector="related_issues_loading_placeholder">
<gl-loading-icon
ref="loadingIcon"
size="sm"
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="{
'gl-cursor-grab': 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"
data-qa-selector="related_issuable_content"
@relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)"
/>
</li>
</ul>
</div>
</div>
</template>