mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
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:
parent
c023591219
commit
9dc5c2f52e
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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}
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user