Browse Source

feat(nc-gui): additional drag & drop support

pull/7611/head
DarkPhoenix2704 9 months ago
parent
commit
bc535a84e3
  1. 94
      packages/nc-gui/components/smartsheet/calendar/MonthView.vue
  2. 29
      packages/nc-gui/components/smartsheet/calendar/SideMenu.vue
  3. 94
      packages/nc-gui/components/smartsheet/calendar/WeekView.vue

94
packages/nc-gui/components/smartsheet/calendar/MonthView.vue

@ -5,8 +5,16 @@ import type { Row } from '#imports'
const emit = defineEmits(['new-record', 'expand-record'])
const { selectedDate, selectedMonth, formattedData, displayField, calendarRange, calDataType, updateRowProperty } =
useCalendarViewStoreOrThrow()
const {
selectedDate,
selectedMonth,
formattedData,
formattedSideBarData,
displayField,
calendarRange,
calDataType,
updateRowProperty,
} = useCalendarViewStoreOrThrow()
const isMondayFirst = ref(true)
@ -299,6 +307,21 @@ const dragStart = (event: DragEvent, record: Row) => {
)
}
const dragEnter = (event: DragEvent) => {
event.preventDefault()
const { top, height, width, left } = calendarGridContainer.value.getBoundingClientRect()
const percentY = (event.clientY - top - window.scrollY) / height
const percentX = (event.clientX - left - window.scrollX) / width
const week = Math.floor(percentY * dates.value.length)
const day = Math.floor(percentX * 7)
const currSelectedDate = dayjs(selectedDate.value).startOf('month').add(week, 'week').add(day, 'day')
selectedDate.value = currSelectedDate.toDate()
}
const dropEvent = (event: DragEvent) => {
event.preventDefault()
const data = event.dataTransfer?.getData('text/plain')
@ -315,9 +338,11 @@ const dropEvent = (event: DragEvent) => {
const { top, height, width, left } = calendarGridContainer.value.getBoundingClientRect()
const percentY = (event.clientY - top - initialClickOffsetY - window.scrollY) / height
const percentX = (event.clientX - left - initialClickOffsetX - window.scrollX) / width
const fromCol = record.rowMeta.range?.fk_from_col
const toCol = record.rowMeta.range?.fk_to_col
const week = Math.floor(percentY * dates.value.length)
const day = Math.floor(percentX * 7)
@ -329,39 +354,59 @@ const dropEvent = (event: DragEvent) => {
...record,
row: {
...record.row,
[record.rowMeta.range.fk_from_col.title]: dayjs(newStartDate).format('YYYY-MM-DD'),
[fromCol.title]: dayjs(newStartDate).format('YYYY-MM-DD'),
},
}
const updateProperty = [record.rowMeta.range.fk_from_col.title]
const updateProperty = [fromCol.title]
if (toCol) {
const fromDate = record.row[fromCol.title] ? dayjs(record.row[fromCol.title]) : null
const toDate = record.row[toCol.title] ? dayjs(record.row[toCol.title]) : null
if (fromDate && toDate) {
endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day')
} else if (fromDate && !toDate) {
endDate = dayjs(newStartDate).endOf('day')
} else if (!fromDate && toDate) {
endDate = dayjs(newStartDate).endOf('day')
} else {
endDate = newStartDate.clone()
}
if (record.rowMeta.range.fk_to_col) {
const diffDays = dayjs(record.row[record.rowMeta.range.fk_to_col.title]).diff(
record.row[record.rowMeta.range.fk_from_col.title],
'day',
)
endDate = dayjs(newStartDate).add(diffDays, 'day')
newRow.row[record.rowMeta.range.fk_to_col.title] = dayjs(endDate).format('YYYY-MM-DD')
updateProperty.push(record.rowMeta.range.fk_to_col.title)
newRow.row[toCol.title] = dayjs(endDate).format('YYYY-MM-DD')
updateProperty.push(toCol.title)
}
if (!newRow) return
dragElement.value.style.boxShadow = 'none'
dragElement.value.classList.remove('hide')
if (dragElement.value) {
formattedData.value = formattedData.value.map((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
dragElement.value = null
if (pk === extractPkFromRow(newRow.row, meta.value.columns)) {
return newRow
}
return r
})
} else {
formattedData.value = [...formattedData.value, newRow]
formattedSideBarData.value = formattedSideBarData.value.filter((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
updateRowProperty(newRow, updateProperty, false)
return pk !== extractPkFromRow(newRow.row, meta.value.columns)
})
}
formattedData.value = formattedData.value.map((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
if (dragElement.value) {
dragElement.value.style.boxShadow = 'none'
dragElement.value.classList.remove('hide')
if (pk === extractPkFromRow(newRow.row, meta.value.columns)) {
return newRow
}
return r
})
dragElement.value = null
}
updateRowProperty(newRow, updateProperty, false)
}
}
@ -395,6 +440,7 @@ const isDateSelected = (date: Date) => {
}"
class="grid h-full pb-7.5"
@drop="dropEvent"
@dragenter.prevent="dragEnter"
>
<div v-for="(week, weekIndex) in dates" :key="weekIndex" class="grid grid-cols-7 grow">
<div

29
packages/nc-gui/components/smartsheet/calendar/SideMenu.vue

@ -45,6 +45,28 @@ const pushToArray = (arr: Array<Row>, record: Row, range) => {
})
}
const dragElement = ref<HTMLElement | null>(null)
const dragStart = (event: DragEvent, record: Row) => {
dragElement.value = event.target as HTMLElement
dragElement.value.classList.add('hide')
dragElement.value.style.boxShadow = '0px 8px 8px -4px rgba(0, 0, 0, 0.04), 0px 20px 24px -4px rgba(0, 0, 0, 0.10)'
const eventRect = dragElement.value.getBoundingClientRect()
const initialClickOffsetX = event.clientX - eventRect.left
const initialClickOffsetY = event.clientY - eventRect.top
event.dataTransfer?.setData(
'text/plain',
JSON.stringify({
record,
initialClickOffsetY,
initialClickOffsetX,
}),
)
}
const renderData = computed<Array<Row>>(() => {
if (!calendarRange.value) return []
@ -281,8 +303,9 @@ const sideBarListScrollHandle = useDebounceFn(async (e: Event) => {
</div>
</div>
<template v-else-if="renderData.length > 0">
<LazySmartsheetRow v-for="(record, rowIndex) in renderData" :key="rowIndex" :row="record">
<LazySmartsheetRow v-for="(record, rowIndex) in renderData" :key="rowIndex">
<LazySmartsheetCalendarSideRecordCard
:draggable="sideBarFilterOption === 'withoutDates'"
:from-date="
record.rowMeta.range?.fk_from_col
? calDataType === UITypes.Date
@ -297,6 +320,7 @@ const sideBarListScrollHandle = useDebounceFn(async (e: Event) => {
)
"
:name="record.row[displayField!.title!]"
:row="record"
:to-date="
record.rowMeta.range!.fk_to_col
? calDataType === UITypes.Date
@ -305,8 +329,9 @@ const sideBarListScrollHandle = useDebounceFn(async (e: Event) => {
: null
"
color="blue"
draggable="true"
@click="emit('expand-record', record)"
@dragstart="dragStart($event, record)"
@dragover.prevent
/>
</LazySmartsheetRow>
</template>

94
packages/nc-gui/components/smartsheet/calendar/WeekView.vue

@ -5,8 +5,16 @@ import type { Row } from '~/lib'
const emits = defineEmits(['expand-record'])
const { selectedDateRange, formattedData, calendarRange, selectedDate, displayField, calDataType, updateRowProperty } =
useCalendarViewStoreOrThrow()
const {
selectedDateRange,
formattedData,
formattedSideBarData,
calendarRange,
selectedDate,
displayField,
calDataType,
updateRowProperty,
} = useCalendarViewStoreOrThrow()
const container = ref(null)
@ -206,6 +214,18 @@ const dragStart = (event: DragEvent, record: Row) => {
)
}
const dragEnter = (event: DragEvent) => {
event.preventDefault()
const { width, left } = container.value.getBoundingClientRect()
const percentX = (event.clientX - left - window.scrollX) / width
const day = Math.floor(percentX * 7)
const currSelectedDate = dayjs(selectedDateRange.value.start).add(day, 'day')
selectedDate.value = currSelectedDate.toDate()
}
const dropEvent = (event: DragEvent) => {
event.preventDefault()
const data = event.dataTransfer?.getData('text/plain')
@ -222,9 +242,11 @@ const dropEvent = (event: DragEvent) => {
const { top, height, width, left } = container.value.getBoundingClientRect()
const percentY = (event.clientY - top - initialClickOffsetY - window.scrollY) / height
const percentX = (event.clientX - left - initialClickOffsetX - window.scrollX) / width
const fromCol = record.rowMeta.range?.fk_from_col
const toCol = record.rowMeta.range?.fk_to_col
const day = Math.floor(percentX * 7)
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day')
@ -235,39 +257,57 @@ const dropEvent = (event: DragEvent) => {
...record,
row: {
...record.row,
[record.rowMeta.range.fk_from_col.title]: dayjs(newStartDate).format('YYYY-MM-DD'),
[fromCol.title]: dayjs(newStartDate).format('YYYY-MM-DD'),
},
}
const updateProperty = [fromCol.title]
if (toCol) {
const fromDate = record.row[fromCol.title] ? dayjs(record.row[fromCol.title]) : null
const toDate = record.row[toCol.title] ? dayjs(record.row[toCol.title]) : null
if (fromDate && toDate) {
endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day')
} else if (fromDate && !toDate) {
endDate = dayjs(newStartDate).endOf('day')
} else if (!fromDate && toDate) {
endDate = dayjs(newStartDate).endOf('day')
} else {
endDate = newStartDate.clone()
}
const updateProperty = [record.rowMeta.range.fk_from_col.title]
if (record.rowMeta.range.fk_to_col) {
const diffDays = dayjs(record.row[record.rowMeta.range.fk_to_col.title]).diff(
record.row[record.rowMeta.range.fk_from_col.title],
'day',
)
endDate = dayjs(newStartDate).add(diffDays, 'day')
newRow.row[record.rowMeta.range.fk_to_col.title] = dayjs(endDate).format('YYYY-MM-DD')
updateProperty.push(record.rowMeta.range.fk_to_col.title)
newRow.row[toCol.title] = dayjs(endDate).format('YYYY-MM-DD')
updateProperty.push(toCol.title)
}
if (!newRow) return
dragElement.value.style.boxShadow = 'none'
dragElement.value.classList.remove('hide')
dragElement.value = null
if (dragElement.value) {
formattedData.value = formattedData.value.map((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
updateRowProperty(newRow, updateProperty, false)
if (pk === extractPkFromRow(newRow.row, meta.value.columns)) {
return newRow
}
return r
})
} else {
formattedData.value = [...formattedData.value, newRow]
formattedSideBarData.value = formattedSideBarData.value.filter((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
return pk !== extractPkFromRow(newRow.row, meta.value.columns)
})
}
formattedData.value = formattedData.value.map((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
if (dragElement.value) {
dragElement.value.style.boxShadow = 'none'
dragElement.value.classList.remove('hide')
if (pk === extractPkFromRow(newRow.row, meta.value.columns)) {
return newRow
}
return r
})
dragElement.value = null
}
console.log(newRow, updateProperty)
updateRowProperty(newRow, updateProperty, false)
}
}
</script>
@ -283,7 +323,7 @@ const dropEvent = (event: DragEvent) => {
{{ dayjs(date).format('DD ddd') }}
</div>
</div>
<div ref="container" class="flex h-[calc(100vh-11.6rem)]" @drop="dropEvent($event)">
<div ref="container" class="flex h-[calc(100vh-11.6rem)]" @dragenter="dragEnter" @drop="dropEvent($event)">
<div
v-for="date in weekDates"
:key="date.toISOString()"

Loading…
Cancel
Save