UBERF-10407: Fix Team display (#8762)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
Signed-off-by: Andrey Sobolev <haiodo@users.noreply.github.com>
This commit is contained in:
Andrey Sobolev
2025-04-29 14:47:20 +07:00
committed by GitHub
parent 3af7fa6f7c
commit 5fa9daee8f
8 changed files with 92 additions and 12 deletions
@@ -29,11 +29,11 @@
closeTooltip,
deviceOptionsStore as deviceInfo,
day as getDay,
getWeekStart,
getWeekDayName,
getWeekStart,
isWeekend,
resizeObserver,
ticker,
isWeekend
ticker
} from '@hcengineering/ui'
import { showMenu } from '@hcengineering/view-resources'
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
@@ -48,6 +48,7 @@
import calendar from '../plugin'
import { isReadOnly, updateReccuringInstance } from '../utils'
import EventElement from './EventElement.svelte'
import TimeDuration from './TimeDuration.svelte'
export let events: Event[]
export let selectedDate: Date = new Date()
@@ -342,6 +343,40 @@
}
}
const calcTime = (events: CalendarItem[]): number => {
if (events.length === 0) return 0
// Extract and sort intervals by start time
const intervals = events.map((it) => [it.date, it.dueDate]).sort((a, b) => a[0] - b[0])
// Merge overlapping intervals
const mergedIntervals = []
let currentStart = intervals[0][0]
let currentEnd = intervals[0][1]
for (let i = 1; i < intervals.length; i++) {
const [nextStart, nextEnd] = intervals[i]
// If intervals overlap, extend the current end if needed
if (nextStart <= currentEnd) {
currentEnd = Math.max(currentEnd, nextEnd)
} else {
// No overlap, add current interval to merged list and start a new one
mergedIntervals.push([currentStart, currentEnd])
currentStart = nextStart
currentEnd = nextEnd
}
}
// Add the last interval
mergedIntervals.push([currentStart, currentEnd])
// Calculate total duration in hours
const totalHours = mergedIntervals.reduce((sum, [start, end]) => sum + (end - start) / (1000 * 60 * 60), 0)
return totalHours * 1000 * 60 * 60
}
const checkIntersect = (date1: CalendarItem | CalendarElement, date2: CalendarItem | CalendarElement): boolean => {
return (
(date2.date <= date1.date && date2.dueDate > date1.date) ||
@@ -818,6 +853,7 @@
{#each [...Array(displayedDaysCount).keys()] as dayOfWeek}
{@const day = getDay(weekStart, dayOfWeek)}
{@const tday = areDatesEqual(todayDate, day)}
{@const tEvents = calcTime(toCalendar(events, day))}
<div class="sticky-header head title" class:center={displayedDaysCount > 1}>
<span class="day" class:today={tday}>{day.getDate()}</span>
{#if tday}
@@ -828,6 +864,11 @@
{:else}
<span class="weekday">{getWeekDayName(day, weekFormat)}</span>
{/if}
{#if tEvents !== 0}
<span style:min-width={'3rem'}>
<TimeDuration value={tEvents} />
</span>
{/if}
</div>
{/each}
{/if}
@@ -0,0 +1,12 @@
<script lang="ts">
import { themeStore, formatDuration } from '@hcengineering/ui'
export let value: number
let duration: string
$: formatDuration(value, $themeStore.language).then((res) => {
duration = res
})
</script>
{duration}
+1 -1
View File
@@ -298,7 +298,7 @@ class Connection implements ClientConnection {
return
}
if (resp.rateLimit !== undefined && resp.rateLimit.remaining < 10) {
if (resp.rateLimit !== undefined && resp.rateLimit.remaining < 50) {
console.log(
'Rate limits:',
resp.rateLimit.remaining,
@@ -8,6 +8,7 @@
import WithTeamData from '../WithTeamData.svelte'
import { toSlots } from '../utils'
import DayPlan from './DayPlan.svelte'
import { personRefByAccountUuidStore } from '@hcengineering/contact-resources'
export let space: Ref<Project>
export let currentDate: Date
@@ -36,9 +37,22 @@
todayFrom,
todayTo
)
$: persons = (project?.members ?? [])
.map((it) => $personRefByAccountUuidStore.get(it))
.filter((it) => it !== undefined)
</script>
<WithTeamData {space} fromDate={yesterdayFrom} toDate={todayTo} bind:project bind:todos bind:slots bind:events />
<WithTeamData
{space}
fromDate={yesterdayFrom}
toDate={todayTo}
bind:project
bind:todos
bind:slots
bind:events
{persons}
/>
<Header bind:currentDate />
{#if project}
@@ -43,7 +43,9 @@
{/each}
{#each gitem.events as event}
<EventItem item={event} showTime={expanded} />
{#if event.overlap === 0}
<EventItem item={event} showTime={expanded} />
{/if}
{/each}
{#if gitem.busy.slots.length > 0}
@@ -16,8 +16,12 @@
import calendar, { Event, getAllEvents } from '@hcengineering/calendar'
import { calendarByIdStore } from '@hcengineering/calendar-resources'
import { getCurrentEmployee, Person } from '@hcengineering/contact'
import { socialIdsByPersonRefStore, personRefByPersonIdStore } from '@hcengineering/contact-resources'
import core, { Doc, IdMap, Ref, Timestamp, Tx, TxCUD, TxCreateDoc, TxUpdateDoc } from '@hcengineering/core'
import {
personRefByAccountUuidStore,
personRefByPersonIdStore,
socialIdsByPersonRefStore
} from '@hcengineering/contact-resources'
import core, { Doc, IdMap, Ref, Timestamp, Tx, TxCreateDoc, TxCUD, TxUpdateDoc } from '@hcengineering/core'
import { Asset } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Project } from '@hcengineering/task'
@@ -43,7 +47,10 @@
let slots: WorkSlot[] = []
let events: Event[] = []
let todos: IdMap<ToDo> = new Map()
let persons: Ref<Person>[] = []
$: persons = (project?.members ?? [])
.map((it) => $personRefByAccountUuidStore.get(it))
.filter((it) => it !== undefined)
const txCreateQuery = createQuery()
@@ -23,6 +23,7 @@
import { groupTeamData, toSlots } from '../utils'
import EventElement from './EventElement.svelte'
import PersonCalendar from './PersonCalendar.svelte'
import { personRefByAccountUuidStore } from '@hcengineering/contact-resources'
export let space: Ref<Project>
export let currentDate: Date
@@ -37,7 +38,10 @@
let slots: WorkSlot[] = []
let events: Event[] = []
let todos: IdMap<ToDo> = new Map()
let persons: Ref<Person>[] = []
$: persons = (project?.members ?? [])
.map((it) => $personRefByAccountUuidStore.get(it))
.filter((it) => it !== undefined)
function calcHourWidth (events: Event[], totalWidth: number): number[] {
const hours = new Map<number, number>()
@@ -173,10 +173,10 @@ function crossWith (a: EventVars, b: EventVars): EventVars[] {
/**
*
* @param events - without overlaps
* @param event -
* @param event - any object with date and dueDate properties
* @returns
*/
function calcOverlap (events: EventVars[], event: Event): { events: EventVars[], total: number } {
function calcOverlap (events: EventVars[], event: EventVars): { events: EventVars[], total: number } {
let tmp: EventVars[] = [{ date: event.date, dueDate: event.dueDate }]
for (const a of events) {
const newTmp: EventVars[] = []