mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-16 05:13:06 +00:00
Fixed display of events for the whole day (#3519)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
021dcafeb0
commit
3058d902fc
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
|
@ -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}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user