Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2024-01-04 13:50:50 +06:00 committed by GitHub
parent a6acb34d92
commit b685aae286
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 27 deletions

View File

@ -382,6 +382,7 @@
events={objects} events={objects}
{mondayStart} {mondayStart}
displayedDaysCount={7} displayedDaysCount={7}
{dragItemId}
startFromWeekStart startFromWeekStart
bind:selectedDate bind:selectedDate
bind:currentDate bind:currentDate
@ -396,6 +397,7 @@
<DayCalendar <DayCalendar
bind:this={dayCalendar} bind:this={dayCalendar}
events={objects} events={objects}
{dragItemId}
{mondayStart} {mondayStart}
displayedDaysCount={mode === CalendarMode.Days ? 3 : 1} displayedDaysCount={mode === CalendarMode.Days ? 3 : 1}
startFromWeekStart={false} startFromWeekStart={false}

View File

@ -62,6 +62,7 @@
export let showHeader: boolean = true export let showHeader: boolean = true
export let showFooter: boolean = true export let showFooter: boolean = true
export let clearCells: boolean = false export let clearCells: boolean = false
export let dragItemId: Ref<Event> | null = null
const client = getClient() const client = getClient()
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -531,14 +532,52 @@
: rem((heightAD + 0.125) * (adMaxRow <= maxAD ? adMaxRow : maxAD) + 0.25) : rem((heightAD + 0.125) * (adMaxRow <= maxAD ? adMaxRow : maxAD) + 0.25)
$: showArrowAD = (!minimizedAD && adMaxRow > maxAD) || (minimizedAD && adMaxRow > minAD) $: showArrowAD = (!minimizedAD && adMaxRow > maxAD) || (minimizedAD && adMaxRow > minAD)
const getMinutes = (e: MouseEvent): number => { const getMinutes = (exactly: number): number => {
let mins: number = 0 const roundStep = 60 / stepsPerHour
for (let i = 0; i < stepsPerHour; i++) { return Math.round(exactly / roundStep) * roundStep
if (e.offsetY >= (i * cellHeight) / stepsPerHour && e.offsetY < ((i + 1) * cellHeight) / stepsPerHour) { }
mins = (i * 60) / stepsPerHour
const getExactly = (e: MouseEvent): number => {
return Math.round((e.offsetY * 60) / cellHeight)
}
const getStickyMinutes = (
minutes: number,
exactly: number,
day: Date,
hour: number,
skipId: Ref<Event> | null
): number => {
const roundStep = 60 / stepsPerHour
// try find event for stick
if (exactly !== minutes) {
const minMinutes = Math.floor(exactly / roundStep) * roundStep
const maxMinutes = Math.ceil(exactly / roundStep) * roundStep
const min = new Date(day).setHours(hour, minMinutes, 0, 0)
const max = new Date(day).setHours(hour, maxMinutes, 0, 0)
const target = new Date(day).setHours(hour, exactly, 0, 0)
const events = newEvents.filter((ev) => ev._id !== skipId && !ev.allDay)
if (events.length > 0) {
const minutes: number[] = []
for (const ev of events) {
if (ev.date >= min && ev.date <= max) {
minutes.push(convertToTime(ev.date).mins)
}
if (ev.dueDate >= min && ev.dueDate <= max) {
minutes.push(convertToTime(ev.dueDate).mins)
}
}
if (minutes.length > 0) {
let nearest = minutes[0]
for (let index = 1; index < minutes.length; index++) {
const minute = minutes[index]
if (Math.abs(minute - target) < Math.abs(nearest - target)) nearest = minute
}
return nearest
}
} }
} }
return mins return minutes
} }
let dragOnOld: CalendarCell | null = null let dragOnOld: CalendarCell | null = null
@ -592,18 +631,12 @@
hour: number hour: number
): void { ): void {
if (resizeId == null && directionResize == null) return if (resizeId == null && directionResize == null) return
let mins: number = 0 const exactly = getExactly(e)
for (let i = 0; i < stepsPerHour; i++) { const minutes = getMinutes(exactly)
if (e.offsetY >= (i * cellHeight) / stepsPerHour && e.offsetY < ((i + 1) * cellHeight) / stepsPerHour) mins = i const mins: number = getStickyMinutes(minutes, exactly, day, hour + startHour, resizeId)
}
if (oldMins === mins) return if (oldMins === mins) return
oldMins = mins oldMins = mins
const newDate = new Date(day).setHours( const newDate = new Date(day).setHours(hour + startHour, mins, 0, 0)
hour + startHour,
(mins * 60) / stepsPerHour + (directionResize === 'top' ? 0 : 60 / stepsPerHour),
0,
0
)
const index = events.findIndex((ev) => ev._id === resizeId) const index = events.findIndex((ev) => ev._id === resizeId)
if (index === -1) return if (index === -1) return
if (directionResize === 'top') { if (directionResize === 'top') {
@ -613,6 +646,7 @@
} }
events = events events = events
} }
function dragStartElement (e: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, event: Event): void { function dragStartElement (e: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, event: Event): void {
if (isReadOnly(event) || event.allDay) return if (isReadOnly(event) || event.allDay) return
if (e.dataTransfer) e.dataTransfer.effectAllowed = 'all' if (e.dataTransfer) e.dataTransfer.effectAllowed = 'all'
@ -623,37 +657,59 @@
closeTooltip() closeTooltip()
setTimeout(() => (dragId = event._id), 50) setTimeout(() => (dragId = event._id), 50)
} }
async function dragEndElement (e: DragEvent) { async function dragEndElement (e: DragEvent) {
const event = events.find((ev) => ev._id === dragId) const event = events.find((ev) => ev._id === dragId)
if (event !== undefined) await updateHandler(event) if (event !== undefined) await updateHandler(event)
dragId = null dragId = null
} }
function dragDrop (e: DragEvent, day: Date, hourOfDay: number): void { function dragDrop (e: DragEvent, day: Date, hourOfDay: number): void {
const newTime = new Date(day).setHours(hourOfDay + startHour, getMinutes(e), 0, 0) const hour = hourOfDay + startHour
const newTime = new Date(day).setHours(hour, getExactly(e), 0, 0)
if (dragId) { if (dragId) {
if (oldTime === -1) oldTime = newTime
const index = events.findIndex((ev) => ev._id === dragId) const index = events.findIndex((ev) => ev._id === dragId)
const diff = newTime - oldTime const diff = newTime - oldTime
if (diff && index !== -1 && oldTime !== -1) { if (diff && index !== -1) {
events[index].date = originDate + diff const diffTime = new Date(originDate + diff)
events[index].dueDate = originDueDate + diff const minutes = convertToTime(diffTime).mins
events = events const roundMinutes = getMinutes(minutes)
const stickyMinutes = getStickyMinutes(roundMinutes, minutes, diffTime, diffTime.getHours(), dragId)
const stickyTime = new Date(diffTime).setMinutes(stickyMinutes, 0, 0)
const stickyDiff = stickyTime - originDate
if (stickyDiff) {
events[index].date = stickyTime
events[index].dueDate = originDueDate + stickyDiff
}
} }
events.sort((a, b) => a.date - b.date)
} else { } else {
const minutes = convertToTime(newTime).mins
const roundMinutes = getMinutes(minutes)
const stickyMinutes = getStickyMinutes(
roundMinutes,
minutes,
new Date(newTime),
new Date(newTime).getHours(),
dragItemId
)
dispatch('dragDrop', { dispatch('dragDrop', {
day, day,
hour: hourOfDay + startHour, hour,
date: new Date(newTime) date: new Date(new Date(newTime).setMinutes(stickyMinutes, 0, 0))
}) })
} }
dragOnOld = null dragOnOld = null
} }
function dragOver (e: DragEvent, day: Date, hourOfDay: number): void { function dragOver (e: DragEvent, day: Date, hourOfDay: number): void {
if (e.dataTransfer) e.dataTransfer.dropEffect = 'move' if (e.dataTransfer) e.dataTransfer.dropEffect = 'move'
e.preventDefault() e.preventDefault()
const dragOn: CalendarCell = { const dragOn: CalendarCell = {
day, day,
hourOfDay, hourOfDay,
minutes: getMinutes(e) minutes: getExactly(e)
} }
if ( if (
dragOnOld !== null && dragOnOld !== null &&
@ -670,11 +726,30 @@
const index = events.findIndex((ev) => ev._id === dragId) const index = events.findIndex((ev) => ev._id === dragId)
const diff = newTime - oldTime const diff = newTime - oldTime
if (diff && index !== -1) { if (diff && index !== -1) {
events[index].date = originDate + diff const diffTime = new Date(originDate + diff)
events[index].dueDate = originDueDate + diff const minutes = convertToTime(diffTime).mins
const roundMinutes = getMinutes(minutes)
const stickyMinutes = getStickyMinutes(roundMinutes, minutes, diffTime, diffTime.getHours(), dragId)
const stickyTime = new Date(diffTime).setMinutes(stickyMinutes, 0, 0)
const stickyDiff = stickyTime - originDate
if (stickyDiff) {
events[index].date = stickyTime
events[index].dueDate = originDueDate + stickyDiff
}
} }
events.sort((a, b) => a.date - b.date) events.sort((a, b) => a.date - b.date)
} else dispatch('dragEnter', { date: new Date(newTime) }) } else {
const minutes = convertToTime(newTime).mins
const roundMinutes = getMinutes(minutes)
const stickyMinutes = getStickyMinutes(
roundMinutes,
minutes,
new Date(newTime),
new Date(newTime).getHours(),
dragItemId
)
dispatch('dragEnter', { date: new Date(new Date(newTime).setMinutes(stickyMinutes, 0, 0)) })
}
} }
function showMenu (ev: MouseEvent, event: Event) { function showMenu (ev: MouseEvent, event: Event) {