UBER-1137: prevent changes of spaces while kanban drag-and-drop (#3928)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2023-11-01 17:55:11 +04:00 committed by GitHub
parent d7089dae74
commit 6ee350103a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 2 deletions

View File

@ -36,6 +36,7 @@
export let dontUpdateRank: boolean = false
export let getUpdateProps: (doc: Doc, state: CategoryType) => DocumentUpdate<Item> | undefined
export let getAvailableCategories: ((doc: Doc) => Promise<CategoryType[]>) | undefined = undefined
const dispatch = createEventDispatcher()
@ -43,6 +44,13 @@
if (dragCard === undefined) {
return
}
const canDrop = !dragCardAvailableCategories || dragCardAvailableCategories.includes(state)
if (!canDrop) {
return
}
let updates = getUpdateProps(dragCard, state)
if (updates === undefined) {
@ -61,6 +69,7 @@
await client.diffUpdate(dragCard, updates)
}
dragCard = undefined
dragCardAvailableCategories = undefined
}
const client = getClient()
@ -70,6 +79,7 @@
let dragCardInitialState: CategoryType
let dragCardInitialPosition: number | undefined
let dragCardState: CategoryType | undefined
let dragCardAvailableCategories: CategoryType[] | undefined
let isDragging = false
@ -84,6 +94,12 @@
function panelDragOver (event: Event | undefined, state: CategoryType): void {
event?.preventDefault()
if (dragCard !== undefined && dragCardState !== state) {
const canDrop = !dragCardAvailableCategories || dragCardAvailableCategories.includes(state)
if (!canDrop) {
return
}
const updates = getUpdateProps(dragCard, state)
if (updates === undefined) {
return
@ -169,7 +185,7 @@
}
isDragging = false
}
function onDragStart (object: Item, state: CategoryType): void {
async function onDragStart (object: Item, state: CategoryType) {
dragCardInitialState = state
dragCardState = state
dragCardInitialRank = object.rank
@ -177,6 +193,7 @@
dragCardInitialPosition = items.findIndex((p) => p._id === object._id)
dragCard = object
isDragging = true
dragCardAvailableCategories = await getAvailableCategories?.(object)
dispatch('obj-focus', object)
}
// eslint-disable-next-line

View File

@ -66,7 +66,8 @@
noCategory,
openDoc,
SelectDirection,
setGroupByValues
setGroupByValues,
statusStore
} from '@hcengineering/view-resources'
import view from '@hcengineering/view-resources/src/plugin'
import { onMount } from 'svelte'
@ -82,6 +83,8 @@
import PriorityEditor from './PriorityEditor.svelte'
import StatusEditor from './StatusEditor.svelte'
import EstimationEditor from './timereport/EstimationEditor.svelte'
import { getStates } from '@hcengineering/task'
import { typeStore } from '@hcengineering/task-resources'
export let space: Ref<Project> | undefined = undefined
export let baseMenuClass: Ref<Class<Doc>> | undefined = undefined
@ -264,6 +267,39 @@
if (enabledConfig(config, 'attachments') && (issue.attachments ?? 0) > 0) return true
return false
}
const getAvailableCategories = async (doc: Doc): Promise<CategoryType[]> => {
const issue = toIssue(doc)
if ([IssuesGrouping.Component, IssuesGrouping.Milestone].includes(groupByKey)) {
const availableCategories = []
const clazz = hierarchy.getAttribute(tracker.class.Issue, groupByKey)
for (const category of categories) {
if (!category || (issue as any)[groupByKey] === category) {
availableCategories.push(category)
} else if (clazz !== undefined && 'to' in clazz.type) {
const categoryDoc = await client.findOne(clazz.type.to as Ref<Class<Doc>>, {
_id: category as Ref<Doc>,
space: issue.space
})
if (categoryDoc) {
availableCategories.push(category)
}
}
}
return availableCategories
}
if (groupByKey === IssuesGrouping.Status) {
const space = await client.findOne(tracker.class.Project, { _id: issue.space })
return getStates(space, $typeStore, $statusStore.byId).map(({ _id }) => _id)
}
return categories
}
</script>
{#if categories.length === 0}
@ -288,6 +324,7 @@
on:obj-focus={(evt) => {
listProvider.updateFocus(evt.detail)
}}
{getAvailableCategories}
selection={listProvider.current($focusStore)}
checked={$selection ?? []}
on:check={(evt) => {