Fixed display of events for the whole day (#3519)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2023-07-25 13:50:55 +03:00 committed by GitHub
parent 021dcafeb0
commit 3058d902fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 245 additions and 96 deletions

View File

@ -25,6 +25,7 @@
areDatesEqual areDatesEqual
} from './internal/DateUtils' } from './internal/DateUtils'
import { CalendarItem } from '../../types' import { CalendarItem } from '../../types'
import { ActionIcon, IconUpOutline, IconDownOutline } from '../..'
export let events: CalendarItem[] export let events: CalendarItem[]
export let mondayStart = true export let mondayStart = true
@ -39,19 +40,25 @@
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
const todayDate = new Date() const todayDate = new Date()
const cellBorder = 1 const ampm = new Intl.DateTimeFormat([], { hour: 'numeric' }).resolvedOptions().hour12
const getTimeFormat = (hour: number): string => {
return ampm ? `${hour > 12 ? hour - 12 : hour}${hour < 12 ? 'am' : 'pm'}` : `${addZero(hour)}:00`
}
$: fontSize = $deviceInfo.fontSize $: fontSize = $deviceInfo.fontSize
$: docHeight = $deviceInfo.docHeight
$: cellHeight = 4 * fontSize $: cellHeight = 4 * fontSize
$: weekMonday = startFromWeekStart $: weekMonday = startFromWeekStart
? getMonday(currentDate, mondayStart) ? getMonday(currentDate, mondayStart)
: new Date(new Date(currentDate).setHours(0, 0, 0, 0)) : new Date(new Date(currentDate).setHours(0, 0, 0, 0))
const ampm = new Intl.DateTimeFormat([], { hour: 'numeric' }).resolvedOptions().hour12 const rem = (n: number): number => n * fontSize
// const timeZone = new Intl.DateTimeFormat([], { hour: 'numeric' }).resolvedOptions().timeZone const cellBorder: number = 1
const heightAD: number = 2
const getTimeFormat = (hour: number): string => { let minHeightAD: number = 0
return ampm ? `${hour > 12 ? hour - 12 : hour}${hour < 12 ? 'am' : 'pm'}` : `${addZero(hour)}:00` let maxHeightAD: number = 0
} let shownHeightAD: number = 0
let shownAD: boolean = false
interface CalendarElement { interface CalendarElement {
id: string id: string
@ -59,11 +66,20 @@
dueDate: Timestamp dueDate: Timestamp
cols: number cols: number
} }
interface CalendarRow { interface CalendarColumn {
elements: CalendarElement[] elements: CalendarElement[]
} }
interface CalendarGrid { interface CalendarGrid {
columns: CalendarRow[] columns: CalendarColumn[]
}
interface CalendarADGrid {
alldays: (string | null)[]
}
interface CalendarADRows {
id: string
row: number
startCol: number
endCol: number
} }
let container: HTMLElement let container: HTMLElement
@ -71,12 +87,20 @@
let calendarWidth: number = 0 let calendarWidth: number = 0
let calendarRect: DOMRect let calendarRect: DOMRect
let colWidth: number = 0 let colWidth: number = 0
let newEvents = events let newEvents = events
let grid: CalendarGrid[] = Array<CalendarGrid>(displayedDaysCount) let grid: CalendarGrid[] = Array<CalendarGrid>(displayedDaysCount)
let alldays: CalendarItem[] = []
let alldaysGrid: CalendarADGrid[] = Array<CalendarADGrid>(displayedDaysCount)
let adMaxRow: number = 1
let adRows: CalendarADRows[]
$: if (newEvents !== events) { $: if (newEvents !== events) {
grid = new Array<CalendarGrid>(displayedDaysCount) grid = new Array<CalendarGrid>(displayedDaysCount)
alldaysGrid = new Array<CalendarADGrid>(displayedDaysCount)
newEvents = events newEvents = events
alldays = []
prepareAllDays()
if (shownAD && adMaxRow < 4) shownAD = false
} }
$: newEvents $: newEvents
.filter((ev) => !ev.allDay) .filter((ev) => !ev.allDay)
@ -143,6 +167,39 @@
} }
} }
} }
const addNullRow = () => {
for (let i = 0; i < displayedDaysCount; i++) alldaysGrid[i].alldays.push(null)
adMaxRow++
}
const prepareAllDays = () => {
alldays = events.filter((ev) => ev.day === -1)
adRows = []
for (let i = 0; i < displayedDaysCount; i++) alldaysGrid[i] = { alldays: [null] }
adMaxRow = 1
alldays.forEach((event) => {
const days = events
.filter((ev) => ev.allDay && ev.day !== -1 && event.eventId === ev.eventId)
.map((ev) => {
return ev.day
})
let emptyRow = 0
for (let checkRow = 0; checkRow < adMaxRow; checkRow++) {
const empty = days.every((day) => alldaysGrid[day].alldays[checkRow] === null)
if (empty) {
emptyRow = checkRow
break
} else if (checkRow === adMaxRow - 1) {
emptyRow = adMaxRow
addNullRow()
break
}
}
adRows.push({ id: event.eventId, row: emptyRow, startCol: days[0], endCol: days[days.length - 1] })
days.forEach((day) => (alldaysGrid[day].alldays[emptyRow] = event.eventId))
})
}
const checkIntersect = (date1: CalendarItem | CalendarElement, date2: CalendarItem | CalendarElement): boolean => { const checkIntersect = (date1: CalendarItem | CalendarElement, date2: CalendarItem | CalendarElement): boolean => {
return ( return (
(date2.date <= date1.date && date2.dueDate > date1.date) || (date2.date <= date1.date && date2.dueDate > date1.date) ||
@ -154,17 +211,10 @@
return { hours: temp.getHours() - startHour, mins: temp.getMinutes() } return { hours: temp.getHours() - startHour, mins: temp.getMinutes() }
} }
const checkSizes = (element: HTMLElement | Element) => {
calendarRect = element.getBoundingClientRect()
calendarWidth = calendarRect.width
colWidth = (calendarWidth - 3.5 * fontSize) / displayedDaysCount
}
const getGridOffset = (mins: number, end: boolean = false): number => { const getGridOffset = (mins: number, end: boolean = false): number => {
if (mins === 0) return end ? 2 + cellBorder : 2 if (mins === 0) return end ? 2 + cellBorder : 2
return mins < 3 ? (end ? 1 : 2) : mins > 57 ? (end ? 2 + cellBorder : 1) : 1 return mins < 3 ? (end ? 1 : 2) : mins > 57 ? (end ? 2 + cellBorder : 1) : 1
} }
const rem = (n: number): number => n * fontSize
const getRect = ( const getRect = (
event: CalendarItem event: CalendarItem
@ -177,7 +227,11 @@
const endTime = const endTime =
event.dueDate > endDay ? { hours: displayedHours - startHour, mins: 0 } : convertToTime(event.dueDate) event.dueDate > endDay ? { hours: displayedHours - startHour, mins: 0 } : convertToTime(event.dueDate)
result.top = result.top =
rem(5.75) + cellHeight * startTime.hours + (startTime.mins / 60) * cellHeight + getGridOffset(startTime.mins) rem(3.5) +
styleAD +
cellHeight * startTime.hours +
(startTime.mins / 60) * cellHeight +
getGridOffset(startTime.mins)
result.bottom = result.bottom =
cellHeight * (displayedHours - startHour - endTime.hours - 1) + cellHeight * (displayedHours - startHour - endTime.hours - 1) +
((60 - endTime.mins) / 60) * cellHeight + ((60 - endTime.mins) / 60) * cellHeight +
@ -203,21 +257,55 @@
return result return result
} }
const getADRect = (event: CalendarItem): { top: number; left: number; width: number } => {
const result = { top: 0, left: 0, width: 0 }
const index = adRows.findIndex((ev) => ev.id === event.eventId)
result.top = rem(0.125 + adRows[index].row * (heightAD + 0.125))
result.left = rem(0.125) + adRows[index].startCol * (colWidth + 0.125)
const w = adRows[index].endCol - adRows[index].startCol
result.width = colWidth + colWidth * w - rem(0.25)
return result
}
const getTimeZone = (): string => {
return new Intl.DateTimeFormat([], { timeZoneName: 'short' }).format(Date.now()).split(' ')[1]
}
onMount(() => { onMount(() => {
if (container) checkSizes(container) if (container) checkSizes(container)
minHeightAD = rem((heightAD + 0.125) * 2 + 0.25)
}) })
const checkSizes = (element: HTMLElement | Element) => {
calendarRect = element.getBoundingClientRect()
calendarWidth = calendarRect.width
colWidth = (calendarWidth - 3.5 * fontSize) / displayedDaysCount
}
$: if (docHeight && calendarRect?.top) {
const proc = ((docHeight - calendarRect.top) * 30) / 100
const temp = rem((heightAD + 0.125) * Math.trunc(proc / rem(heightAD + 0.125)) + 0.25)
maxHeightAD = temp < minHeightAD ? minHeightAD : temp
shownHeightAD = rem((heightAD + 0.125) * adMaxRow + 0.25)
}
$: styleAD = shownAD
? shownHeightAD > maxHeightAD
? maxHeightAD
: shownHeightAD
: rem((heightAD + 0.125) * adMaxRow + 0.25) > maxHeightAD && maxHeightAD === minHeightAD
? rem((heightAD + 0.125) * (adMaxRow < 3 ? adMaxRow : 2) + 0.25)
: rem((heightAD + 0.125) * (adMaxRow < 4 ? adMaxRow : 3) + 0.25)
</script> </script>
<Scroller bind:divScroll={scroller} fade={{ multipler: { top: 5.75, bottom: 0 } }}> <Scroller bind:divScroll={scroller} fade={{ multipler: { top: 3.5 + styleAD / fontSize, bottom: 0 } }}>
<div <div
bind:this={container} bind:this={container}
class="calendar-container" class="calendar-container"
style:grid={`[header] 3.5rem [all-day] 2.25rem repeat(${ style:grid={`[header] 3.5rem [all-day] ${styleAD}px repeat(${
(displayedHours - startHour) * 2 (displayedHours - startHour) * 2
}, [row-start] 2rem) / [time-col] 3.5rem repeat(${displayedDaysCount}, [col-start] 1fr)`} }, [row-start] 2rem) / [time-col] 3.5rem repeat(${displayedDaysCount}, [col-start] 1fr)`}
use:resizeObserver={(element) => checkSizes(element)} use:resizeObserver={(element) => checkSizes(element)}
> >
<div class="sticky-header head center"><span class="zone">CEST</span></div> <div class="sticky-header head center"><span class="zone">{getTimeZone()}</span></div>
{#each [...Array(displayedDaysCount).keys()] as dayOfWeek} {#each [...Array(displayedDaysCount).keys()] as dayOfWeek}
{@const day = getDay(weekMonday, dayOfWeek)} {@const day = getDay(weekMonday, dayOfWeek)}
<div class="sticky-header head title" class:center={displayedDaysCount > 1}> <div class="sticky-header head title" class:center={displayedDaysCount > 1}>
@ -226,26 +314,58 @@
</div> </div>
{/each} {/each}
<div class="sticky-header center text-sm content-dark-color">All day</div> <div class="sticky-header allday-header text-sm content-dark-color">
{#each [...Array(displayedDaysCount).keys()] as dayOfWeek} All day
{@const day = getDay(weekMonday, dayOfWeek)} {#if adMaxRow > 3}
{@const alldays = events.filter((ev) => ev.allDay && ev.day === dayOfWeek)} <ActionIcon
<!-- svelte-ignore a11y-click-events-have-key-events --> icon={shownAD ? IconUpOutline : IconDownOutline}
<div size={'small'}
class="sticky-header" action={() => {
class:allday-container={alldays.length > 0} shownAD = !shownAD
style:width={`${colWidth}px`} }}
style:grid-template-columns={`repeat(${alldays.length}, minmax(0, 1fr))`} />
on:click|stopPropagation={() => {/if}
dispatch('create', { day, hour: -1, halfHour: false, date: new Date(day.setHours(0, 0, 0, 0)) })} </div>
> <div class="sticky-header allday-container" style:grid-column={`col-start 1 / span ${displayedDaysCount}`}>
{#each alldays as ad} {#if shownHeightAD > maxHeightAD && shownAD}
<div class="allday-event"> <Scroller noFade={false}>
<slot name="allday" id={ad.eventId} width={colWidth / alldays.length} /> {#key calendarWidth || displayedDaysCount}
</div> <div style:min-height={`${shownHeightAD - cellBorder * 2}px`} />
{/each} {#each alldays as event, i}
</div> {@const rect = getADRect(event)}
{/each} <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:height={`${heightAD}rem`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
tabindex={500 + i}
>
<slot name="allday" id={event.eventId} width={rect.width} />
</div>
{/each}
{/key}
</Scroller>
{:else}
{#key calendarWidth || displayedDaysCount}
{#each alldays as event, i}
{@const rect = getADRect(event)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:height={`${heightAD}rem`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
tabindex={500 + i}
>
<slot name="allday" id={event.eventId} width={rect.width} />
</div>
{/each}
{/key}
{/if}
</div>
{#each [...Array(displayedHours - startHour).keys()] as hourOfDay} {#each [...Array(displayedHours - startHour).keys()] as hourOfDay}
{#if hourOfDay === 0} {#if hourOfDay === 0}
@ -264,13 +384,13 @@
<!-- svelte-ignore a11y-click-events-have-key-events --> <!-- svelte-ignore a11y-click-events-have-key-events -->
<div <div
class="empty-cell" class="empty-cell"
style:width={`${colWidth}px`}
style:grid-column={`col-start ${dayOfWeek + 1} / ${dayOfWeek + 2}`} style:grid-column={`col-start ${dayOfWeek + 1} / ${dayOfWeek + 2}`}
style:grid-row={`row-start ${hourOfDay * 2 + 1} / row-start ${hourOfDay * 2 + 3}`} style:grid-row={`row-start ${hourOfDay * 2 + 1} / row-start ${hourOfDay * 2 + 3}`}
on:click|stopPropagation={() => { on:click|stopPropagation={() => {
dispatch('create', { dispatch('create', {
day, date: new Date(day.setHours(hourOfDay + startHour, 0, 0, 0)),
hour: hourOfDay + startHour, withTime: true
date: new Date(day.setHours(hourOfDay + startHour, 0, 0, 0))
}) })
}} }}
/> />
@ -278,22 +398,22 @@
{#if hourOfDay === displayedHours - startHour - 1}<div class="clear-cell" />{/if} {#if hourOfDay === displayedHours - startHour - 1}<div class="clear-cell" />{/if}
{/each} {/each}
{#key calendarWidth || displayedDaysCount} {#key styleAD}{#key calendarWidth}{#key displayedDaysCount}
{#each events.filter((ev) => !ev.allDay) as event, i} {#each newEvents.filter((ev) => !ev.allDay) as event, i}
{@const rect = getRect(event)} {@const rect = getRect(event)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex --> <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div <div
class="calendar-element" class="calendar-element"
style:top={`${rect.top}px`} style:top={`${rect.top}px`}
style:bottom={`${rect.bottom}px`} style:bottom={`${rect.bottom}px`}
style:left={`${rect.left}px`} style:left={`${rect.left}px`}
style:right={`${rect.right}px`} style:right={`${rect.right}px`}
tabindex={1000 + i} tabindex={1000 + i}
> >
<slot name="event" id={event.eventId} width={rect.width} /> <slot name="event" id={event.eventId} width={rect.width} />
</div> </div>
{/each} {/each}
{/key} {/key}{/key}{/key}
</div> </div>
</Scroller> </Scroller>
@ -365,15 +485,15 @@
display: flex; display: flex;
align-items: center; align-items: center;
} }
&.allday-header {
flex-direction: column;
justify-content: space-between;
padding: 0.625rem 0.125rem;
}
&.allday-container { &.allday-container {
display: inline-grid; overflow: hidden;
justify-items: stretch;
gap: 0.125rem;
padding: 0.125rem;
max-width: 100%;
.allday-event { .allday-event {
background-color: red;
border-radius: 0.25rem; border-radius: 0.25rem;
} }
} }

View File

@ -132,6 +132,7 @@ export { default as IconUp } from './components/icons/Up.svelte'
export { default as IconDown } from './components/icons/Down.svelte' export { default as IconDown } from './components/icons/Down.svelte'
export { default as IconUpOutline } from './components/icons/UpOutline.svelte' export { default as IconUpOutline } from './components/icons/UpOutline.svelte'
export { default as IconDownOutline } from './components/icons/DownOutline.svelte' export { default as IconDownOutline } from './components/icons/DownOutline.svelte'
export { default as IconDropdown } from './components/icons/Dropdown.svelte'
export { default as IconShare } from './components/icons/Share.svelte' export { default as IconShare } from './components/icons/Share.svelte'
export { default as IconDelete } from './components/icons/Delete.svelte' export { default as IconDelete } from './components/icons/Delete.svelte'
export { default as IconActivityEdit } from './components/icons/ActivityEdit.svelte' export { default as IconActivityEdit } from './components/icons/ActivityEdit.svelte'

View File

@ -114,6 +114,7 @@
const calendarsQuery = createQuery() const calendarsQuery = createQuery()
let calendars: Calendar[] = [] let calendars: Calendar[] = []
const offsetTZ = new Date().getTimezoneOffset() * 60 * 1000
calendarsQuery.query(calendar.class.Calendar, { createdBy: getCurrentAccount()._id }, (res) => { calendarsQuery.query(calendar.class.Calendar, { createdBy: getCurrentAccount()._id }, (res) => {
calendars = res calendars = res
@ -234,27 +235,43 @@
): CalendarItem[] => { ): CalendarItem[] => {
const result: CalendarItem[] = [] const result: CalendarItem[] = []
for (let day = 0; day < days; day++) { for (let day = 0; day < days; day++) {
const startDate = new Date(MILLISECONDS_IN_DAY * day + date.getTime()).setHours(startHour, 0, 0) const startDay = new Date(MILLISECONDS_IN_DAY * day + date.getTime()).setHours(0, 0, 0, 0)
const lastDate = new Date(MILLISECONDS_IN_DAY * day + date.getTime()).setHours(endHour - 1, 59, 59) const startDate = new Date(MILLISECONDS_IN_DAY * day + date.getTime()).setHours(startHour, 0, 0, 0)
const lastDate = new Date(MILLISECONDS_IN_DAY * day + date.getTime()).setHours(endHour, 0, 0, 0)
events.forEach((event) => { events.forEach((event) => {
const eventStart = event.allDay const eventStart = event.allDay ? event.date + offsetTZ : event.date
? new Date(event.date + new Date().getTimezoneOffset() * 60 * 1000).getTime() const eventEnd = event.allDay ? event.dueDate + offsetTZ : event.dueDate
: event.date if ((eventStart < lastDate && eventEnd > startDate) || (eventStart === eventEnd && eventStart === startDay)) {
const eventEnd = event.allDay
? new Date(event.dueDate + new Date().getTimezoneOffset() * 60 * 1000).getTime()
: event.dueDate
if ((eventStart <= startDate && eventEnd > startDate) || (eventStart >= startDate && eventStart < lastDate)) {
result.push({ result.push({
eventId: event.eventId, eventId: event.eventId,
allDay: event.allDay, allDay: event.allDay,
date: event.date, date: eventStart,
dueDate: event.dueDate, dueDate: eventEnd,
day, day,
access: event.access access: event.access
}) })
} }
}) })
} }
const sd = date.setHours(0, 0, 0, 0)
const ld = new Date(MILLISECONDS_IN_DAY * (days - 1) + date.getTime()).setHours(23, 59, 59, 999)
events
.filter((ev) => ev.allDay)
.sort((a, b) => b.dueDate - b.date - (a.dueDate - a.date))
.forEach((event) => {
const eventStart = event.date + offsetTZ
const eventEnd = event.dueDate + offsetTZ
if ((eventStart < ld && eventEnd > sd) || (eventStart === eventEnd && eventStart === sd)) {
result.push({
eventId: event.eventId,
allDay: event.allDay,
date: eventStart,
dueDate: eventEnd,
day: -1,
access: event.access
})
}
})
return result return result
} }
</script> </script>
@ -361,7 +378,7 @@
startFromWeekStart={false} startFromWeekStart={false}
bind:selectedDate bind:selectedDate
bind:currentDate bind:currentDate
on:create={(e) => showCreateDialog(e.detail.date, true)} on:create={(e) => showCreateDialog(e.detail.date, e.detail.withTime)}
> >
<svelte:fragment slot="allday" let:id let:width> <svelte:fragment slot="allday" let:id let:width>
{@const event = objects.find((event) => event.eventId === id)} {@const event = objects.find((event) => event.eventId === id)}
@ -371,7 +388,7 @@
{width} {width}
allday allday
on:create={(e) => { on:create={(e) => {
showCreateDialog(e.detail, true) showCreateDialog(e.detail.date, e.detail.withTime)
}} }}
/> />
{/if} {/if}
@ -383,7 +400,7 @@
{event} {event}
{width} {width}
on:create={(e) => { on:create={(e) => {
showCreateDialog(e.detail, true) showCreateDialog(e.detail.date, e.detail.withTime)
}} }}
/> />
{/if} {/if}
@ -398,7 +415,7 @@
startFromWeekStart={false} startFromWeekStart={false}
bind:selectedDate bind:selectedDate
bind:currentDate bind:currentDate
on:create={(e) => showCreateDialog(e.detail.date, true)} on:create={(e) => showCreateDialog(e.detail.date, e.detail.withTime)}
> >
<svelte:fragment slot="allday" let:id let:width> <svelte:fragment slot="allday" let:id let:width>
{@const event = objects.find((event) => event.eventId === id)} {@const event = objects.find((event) => event.eventId === id)}
@ -408,7 +425,7 @@
{width} {width}
allday allday
on:create={(e) => { on:create={(e) => {
showCreateDialog(e.detail, true) showCreateDialog(e.detail.date, e.detail.withTime)
}} }}
/> />
{/if} {/if}
@ -420,7 +437,7 @@
{event} {event}
{width} {width}
on:create={(e) => { on:create={(e) => {
showCreateDialog(e.detail, true) showCreateDialog(e.detail.date, e.detail.withTime)
}} }}
/> />
{/if} {/if}

View File

@ -16,7 +16,7 @@
import { Calendar, generateEventId } from '@hcengineering/calendar' import { Calendar, generateEventId } from '@hcengineering/calendar'
import { Employee, EmployeeAccount } from '@hcengineering/contact' import { Employee, EmployeeAccount } from '@hcengineering/contact'
import { UserBoxList } from '@hcengineering/contact-resources' import { UserBoxList } from '@hcengineering/contact-resources'
import { Class, DateRangeMode, Doc, Ref, getCurrentAccount } from '@hcengineering/core' import { Class, DateRangeMode, Doc, Ref, Timestamp, getCurrentAccount } from '@hcengineering/core'
import { Card, getClient } from '@hcengineering/presentation' import { Card, getClient } from '@hcengineering/presentation'
import ui, { DateRangePresenter, EditBox, ToggleWithLabel } from '@hcengineering/ui' import ui, { DateRangePresenter, EditBox, ToggleWithLabel } from '@hcengineering/ui'
import { createEventDispatcher, tick } from 'svelte' import { createEventDispatcher, tick } from 'svelte'
@ -29,8 +29,8 @@
export let withTime = false export let withTime = false
const now = new Date() const now = new Date()
const defaultDuration = 30 * 60 * 1000 const defaultDuration = 60 * 60 * 1000
const allDayDuration = 24 * 60 * 60 * 1000 const allDayDuration = 24 * 60 * 60 * 1000 - 1
let startDate = let startDate =
date === undefined ? now.getTime() : withTime ? date.getTime() : date.setHours(now.getHours(), now.getMinutes()) date === undefined ? now.getTime() : withTime ? date.getTime() : date.setHours(now.getHours(), now.getMinutes())
@ -49,6 +49,19 @@
return title !== undefined && title.trim().length === 0 && participants.length === 0 return title !== undefined && title.trim().length === 0 && participants.length === 0
} }
const saveUTC = (date: Timestamp): Timestamp => {
const utcdate = new Date(date)
return Date.UTC(
utcdate.getFullYear(),
utcdate.getMonth(),
utcdate.getDate(),
utcdate.getHours(),
utcdate.getMinutes(),
utcdate.getSeconds(),
utcdate.getMilliseconds()
)
}
async function saveEvent () { async function saveEvent () {
let date: number | undefined let date: number | undefined
if (startDate != null) date = startDate if (startDate != null) date = startDate
@ -56,8 +69,8 @@
const space = `${getCurrentAccount()._id}_calendar` as Ref<Calendar> const space = `${getCurrentAccount()._id}_calendar` as Ref<Calendar>
await client.addCollection(calendar.class.Event, space, attachedTo, attachedToClass, 'events', { await client.addCollection(calendar.class.Event, space, attachedTo, attachedToClass, 'events', {
eventId: generateEventId(), eventId: generateEventId(),
date: allDay ? new Date(date).setUTCHours(0, 0, 0, 0) : date, date: allDay ? saveUTC(date) : date,
dueDate: allDay ? new Date(dueDate).setUTCHours(0, 0, 0, 0) : dueDate, dueDate: allDay ? saveUTC(dueDate) : dueDate,
description: '', description: '',
participants, participants,
title, title,
@ -68,7 +81,7 @@
const handleNewStartDate = async (newStartDate: number | null) => { const handleNewStartDate = async (newStartDate: number | null) => {
if (newStartDate !== null) { if (newStartDate !== null) {
startDate = newStartDate startDate = allDay ? new Date(newStartDate).setHours(0, 0, 0, 0) : newStartDate
dueDate = startDate + (allDay ? allDayDuration : duration) dueDate = startDate + (allDay ? allDayDuration : duration)
await tick() await tick()
dueDateRef.adaptValue() dueDateRef.adaptValue()
@ -79,8 +92,8 @@
if (newDueDate !== null) { if (newDueDate !== null) {
const diff = newDueDate - startDate const diff = newDueDate - startDate
if (diff > 0) { if (diff > 0) {
dueDate = newDueDate dueDate = allDay ? new Date(newDueDate).setHours(23, 59, 59, 999) : newDueDate
duration = diff duration = dueDate - startDate
} else { } else {
dueDate = startDate + (allDay ? allDayDuration : duration) dueDate = startDate + (allDay ? allDayDuration : duration)
} }
@ -91,11 +104,9 @@
async function allDayChangeHandler () { async function allDayChangeHandler () {
if (allDay) { if (allDay) {
startDate = new Date(startDate).setUTCHours(0, 0, 0, 0) startDate = new Date(startDate).setHours(0, 0, 0, 0)
if (dueDate - startDate < allDayDuration) { if (dueDate - startDate < allDayDuration) dueDate = allDayDuration + startDate
dueDate = allDayDuration + startDate else dueDate = new Date(dueDate).setHours(23, 59, 59, 999)
}
dueDate = new Date(dueDate).setUTCHours(0, 0, 0, 0)
} else { } else {
dueDate = startDate + defaultDuration dueDate = startDate + defaultDuration
} }