UBER-674: the calendar starts from the current time. Calendar fixes. (#3671)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2023-09-08 07:37:31 +03:00 committed by GitHub
parent c023591219
commit 9dc5c2f52e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 15 deletions

View File

@ -214,6 +214,7 @@ input.search {
align-items: center; align-items: center;
flex-wrap: nowrap; flex-wrap: nowrap;
min-width: 0; min-width: 0;
min-height: 0;
} }
.flex-row-stretch { .flex-row-stretch {
display: flex; display: flex;

View File

@ -23,13 +23,11 @@
.ac-header { .ac-header {
padding: 0.5rem 2.25rem; padding: 0.5rem 2.25rem;
background-color: var(--theme-comp-header-color);
// height: 3.5rem; // height: 3.5rem;
// min-height: 2.5rem; // min-height: 2.5rem;
&.caption-height { &:not(.withoutBackground) { background-color: var(--theme-comp-header-color); }
min-height: 3.25rem; &.caption-height { min-height: 3.25rem; }
}
&.search-start { padding-left: 1.75rem; } &.search-start { padding-left: 1.75rem; }
&.tabs-start { padding: 0 2.25rem; } &.tabs-start { padding: 0 2.25rem; }
&.short { &.short {

View File

@ -14,7 +14,7 @@
}) })
</script> </script>
<div class="ac-header tabs-start full"> <div class="ac-header withoutBackground tabs-start full">
<TabList <TabList
items={modeList} items={modeList}
selected={props.mode} selected={props.mode}

View File

@ -65,6 +65,7 @@
let currentDate: Date = new Date() let currentDate: Date = new Date()
let selectedDate: Date = new Date() let selectedDate: Date = new Date()
let dayCalendar: DayCalendar
let raw: Event[] = [] let raw: Event[] = []
let visible: Event[] = [] let visible: Event[] = []
let objects: Event[] = [] let objects: Event[] = []
@ -170,6 +171,7 @@
function inc (val: number): void { function inc (val: number): void {
if (val === 0) { if (val === 0) {
currentDate = new Date() currentDate = new Date()
dayCalendar.scrollToTime(currentDate)
return return
} }
switch (mode) { switch (mode) {
@ -379,6 +381,7 @@
</MonthCalendar> </MonthCalendar>
{:else if mode === CalendarMode.Week} {:else if mode === CalendarMode.Week}
<DayCalendar <DayCalendar
bind:this={dayCalendar}
events={objects} events={objects}
{mondayStart} {mondayStart}
displayedDaysCount={7} displayedDaysCount={7}
@ -392,6 +395,7 @@
{:else if mode === CalendarMode.Day || mode === CalendarMode.Days} {:else if mode === CalendarMode.Day || mode === CalendarMode.Days}
{#key mode} {#key mode}
<DayCalendar <DayCalendar
bind:this={dayCalendar}
events={objects} events={objects}
{mondayStart} {mondayStart}
displayedDaysCount={mode === CalendarMode.Days ? 3 : 1} displayedDaysCount={mode === CalendarMode.Days ? 3 : 1}
@ -412,6 +416,8 @@
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 0.75rem 1.75rem 0.75rem 2.25rem; padding: 0.75rem 1.75rem 0.75rem 2.25rem;
min-width: 0;
min-height: 0;
.title { .title {
font-size: 1.25rem; font-size: 1.25rem;

View File

@ -31,7 +31,7 @@
getWeekDayName, getWeekDayName,
resizeObserver resizeObserver
} from '@hcengineering/ui' } from '@hcengineering/ui'
import { createEventDispatcher, onMount } from 'svelte' import { createEventDispatcher, onDestroy, onMount } from 'svelte'
import calendar from '../plugin' import calendar from '../plugin'
import EventElement from './EventElement.svelte' import EventElement from './EventElement.svelte'
@ -50,8 +50,13 @@
const todayDate = new Date() const todayDate = new Date()
const ampm = new Intl.DateTimeFormat([], { hour: 'numeric' }).resolvedOptions().hour12 const ampm = new Intl.DateTimeFormat([], { hour: 'numeric' }).resolvedOptions().hour12
const getTimeFormat = (hour: number): string => { const getTimeFormat = (hour: number, min: number = 0): string => {
return ampm ? `${hour > 12 ? hour - 12 : hour}${hour < 12 ? 'am' : 'pm'}` : `${addZero(hour)}:00` if (min === 0) return ampm ? `${hour > 12 ? hour - 12 : hour}${hour < 12 ? 'am' : 'pm'}` : `${addZero(hour)}:00`
else {
return ampm
? `${hour > 12 ? hour - 12 : hour}:${addZero(min)}${hour < 12 ? 'am' : 'pm'}`
: `${addZero(hour)}:${addZero(min)}`
}
} }
const rem = (n: number): number => n * fontSize const rem = (n: number): number => n * fontSize
@ -137,11 +142,15 @@
endCol: number endCol: number
} }
let timer: any
let container: HTMLElement let container: HTMLElement
let scroller: HTMLElement let scroller: HTMLElement
let calendarWidth: number = 0 let calendarWidth: number = 0
let calendarRect: DOMRect let calendarRect: DOMRect
let colWidth: number = 0 let colWidth: number = 0
let nowLineTop: number = -1
let timeNow: string = '--:--'
let nowLineStyle: string = ''
let newEvents = calendarEvents let newEvents = calendarEvents
let grid: CalendarGrid[] = Array<CalendarGrid>(displayedDaysCount) let grid: CalendarGrid[] = Array<CalendarGrid>(displayedDaysCount)
let alldays: CalendarItem[] = [] let alldays: CalendarItem[] = []
@ -317,7 +326,7 @@
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 < 2 ? (end ? 1 : 2) : mins >= 57 ? (end ? 1 + cellBorder : 1) : 1
} }
const getRect = ( const getRect = (
@ -424,9 +433,53 @@
return new Intl.DateTimeFormat([], { timeZoneName: 'short' }).format(Date.now()).split(' ')[1] return new Intl.DateTimeFormat([], { timeZoneName: 'short' }).format(Date.now()).split(' ')[1]
} }
const getTopOffset = (date: Date): number => {
const d = convertToTime(date)
return (
(showHeader ? rem(3.5) : 0) +
styleAD +
cellHeight * d.hours +
(d.mins / 60) * cellHeight +
(d.mins > 50 ? -getGridOffset(d.mins, true) : d.mins < 10 ? getGridOffset(d.mins) : 0)
)
}
const renderNow = (): void => {
const d = new Date()
const n = convertToTime(d)
nowLineStyle =
n.hours <= startHour && n.mins < 10
? ' lowerLabel'
: n.hours >= displayedHours + startHour - 1 && n.mins > 50
? ' upperLabel'
: ''
timeNow = getTimeFormat(n.hours, n.mins)
nowLineTop = getTopOffset(d)
}
const checkNowLine = (): void => {
if (timer) clearInterval(timer)
let equal = false
for (let i = 0; i < displayedDaysCount; i++) if (areDatesEqual(getDay(weekMonday, i), todayDate)) equal = true
if (equal) {
renderNow()
timer = setInterval(() => renderNow(), 1000)
} else nowLineTop = -1
}
export const scrollToTime = (date: Date): void => {
const top = getTopOffset(date)
const offset = (scroller.getBoundingClientRect().height - rem(heightAD + 0.25)) / 2
scroller.scrollTo({ top: top - offset })
}
$: if (currentDate) checkNowLine()
onMount(() => { onMount(() => {
if (container) checkSizes(container)
minHeightAD = rem((heightAD + 0.125) * minAD + 0.25) minHeightAD = rem((heightAD + 0.125) * minAD + 0.25)
if (container) {
checkSizes(container)
scrollToTime(todayDate)
}
})
onDestroy(() => {
if (timer) clearInterval(timer)
}) })
const checkSizes = (element: HTMLElement | Element) => { const checkSizes = (element: HTMLElement | Element) => {
@ -667,10 +720,63 @@
{/if} {/if}
{/each} {/each}
{/key} {/key}
{#key currentDate}
{#if nowLineTop !== -1}
<div data-now={timeNow} class="now-line{nowLineStyle}" style:top={`${nowLineTop}px`} />
{/if}
{/key}
</div> </div>
</Scroller> </Scroller>
<style lang="scss"> <style lang="scss">
.calendar-container {
will-change: transform;
position: relative;
display: grid;
.now-line,
.now-line::before {
position: absolute;
background-color: var(--highlight-red);
}
.now-line {
left: 3rem;
right: 0;
width: 100%;
height: 1px;
min-height: 1px;
max-height: 1px;
pointer-events: none;
z-index: 2;
&::before {
content: '';
top: -0.5rem;
left: -2.75rem;
right: calc(100% - 0.25rem);
height: 1rem;
border-radius: 0.125rem;
}
&::after {
position: absolute;
content: attr(data-now);
top: -0.5rem;
left: -1.25rem;
font-weight: 500;
font-size: 0.75rem;
color: var(--accented-button-color);
transform: translateX(-50%);
}
&.upperLabel::before,
&.upperLabel::after {
top: -0.875rem;
}
&.lowerLabel::before,
&.lowerLabel::after {
top: -0.125rem;
}
}
}
.empty-cell { .empty-cell {
border-left: 1px solid var(--theme-divider-color); border-left: 1px solid var(--theme-divider-color);
border-bottom: 1px solid var(--theme-divider-color); border-bottom: 1px solid var(--theme-divider-color);
@ -710,6 +816,8 @@
} }
&.zm { &.zm {
top: var(--calendar-ad-height, 2.25rem); top: var(--calendar-ad-height, 2.25rem);
mask-image: linear-gradient(to top, #0000, #000f 0.5rem, #000f calc(100% - 0.5rem), #0000 100%);
z-index: 1;
} }
&.center { &.center {
justify-content: center; justify-content: center;
@ -778,9 +886,4 @@
} }
} }
} }
.calendar-container {
will-change: transform;
position: relative;
display: grid;
}
</style> </style>