Fix team planning event duplicates (#5605)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2024-05-15 23:13:42 +05:00 committed by GitHub
parent 9325c7f8de
commit cbddcf9a3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 41 additions and 60 deletions

View File

@ -39,7 +39,7 @@
getMonday, getMonday,
showPopup showPopup
} from '@hcengineering/ui' } from '@hcengineering/ui'
import { CalendarMode, DayCalendar, calendarStore, hidePrivateEvents } from '../index' import { CalendarMode, DayCalendar, calendarByIdStore, hidePrivateEvents } from '../index'
import calendar from '../plugin' import calendar from '../plugin'
import Day from './Day.svelte' import Day from './Day.svelte'
@ -140,7 +140,7 @@
) )
} }
$: update(_class, query, calendars, options) $: update(_class, query, calendars, options)
$: visible = hidePrivateEvents(raw, $calendarStore) $: visible = hidePrivateEvents(raw, $calendarByIdStore)
$: objects = getAllEvents(visible, from, to) $: objects = getAllEvents(visible, from, to)
function inRange (start: Date, end: Date, startPeriod: Date, period: 'day' | 'hour'): boolean { function inRange (start: Date, end: Date, startPeriod: Date, period: 'day' | 'hour'): boolean {
@ -276,7 +276,7 @@
function clear (dragItem: Doc | undefined) { function clear (dragItem: Doc | undefined) {
if (dragItem === undefined) { if (dragItem === undefined) {
raw = raw.filter((p) => p._id !== dragItemId) raw = raw.filter((p) => p._id !== dragItemId)
visible = hidePrivateEvents(raw, $calendarStore) visible = hidePrivateEvents(raw, $calendarByIdStore)
objects = getAllEvents(visible, from, to) objects = getAllEvents(visible, from, to)
} }
} }

View File

@ -19,7 +19,7 @@
import { Component, MILLISECONDS_IN_MINUTE, showPopup, tooltip } from '@hcengineering/ui' import { Component, MILLISECONDS_IN_MINUTE, showPopup, tooltip } from '@hcengineering/ui'
import view, { ObjectEditor } from '@hcengineering/view' import view, { ObjectEditor } from '@hcengineering/view'
import { showMenu } from '@hcengineering/view-resources' import { showMenu } from '@hcengineering/view-resources'
import { calendarStore, isVisible } from '../utils' import { calendarByIdStore, isVisible } from '../utils'
import EventPresenter from './EventPresenter.svelte' import EventPresenter from './EventPresenter.svelte'
export let event: Event export let event: Event
@ -48,7 +48,7 @@
let div: HTMLDivElement let div: HTMLDivElement
$: visible = isVisible(event, $calendarStore) $: visible = isVisible(event, $calendarByIdStore)
function contextMenu (e: MouseEvent): void { function contextMenu (e: MouseEvent): void {
showMenu(e, { object: event }) showMenu(e, { object: event })

View File

@ -70,7 +70,9 @@ export function isVisible (value: Event, calendars: IdMap<Calendar>): boolean {
} }
} }
export const calendarStore = writable<IdMap<Calendar>>(new Map()) export const calendarByIdStore = writable<IdMap<Calendar>>(new Map())
export const calendarStore = writable<Calendar[]>([])
export const visibleCalendarStore = writable<Calendar[]>([])
function fillStores (): void { function fillStores (): void {
const client = getClient() const client = getClient()
@ -78,7 +80,9 @@ function fillStores (): void {
if (client !== undefined) { if (client !== undefined) {
const query = createQuery(true) const query = createQuery(true)
query.query(calendar.class.Calendar, {}, (res) => { query.query(calendar.class.Calendar, {}, (res) => {
calendarStore.set(toIdMap(res)) calendarStore.set(res)
visibleCalendarStore.set(res.filter((p) => !p.hidden))
calendarByIdStore.set(toIdMap(res))
}) })
} else { } else {
setTimeout(() => { setTimeout(() => {

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import calendar, { Calendar, Event, generateEventId, getAllEvents } from '@hcengineering/calendar' import calendar, { Calendar, Event, generateEventId, getAllEvents } from '@hcengineering/calendar'
import { DayCalendar, calendarStore, hidePrivateEvents } from '@hcengineering/calendar-resources' import { DayCalendar, calendarByIdStore, hidePrivateEvents } from '@hcengineering/calendar-resources'
import { PersonAccount } from '@hcengineering/contact' import { PersonAccount } from '@hcengineering/contact'
import { Ref, SortingOrder, Timestamp, getCurrentAccount } from '@hcengineering/core' import { Ref, SortingOrder, Timestamp, getCurrentAccount } from '@hcengineering/core'
import { IntlString, getEmbeddedLabel } from '@hcengineering/platform' import { IntlString, getEmbeddedLabel } from '@hcengineering/platform'
@ -75,7 +75,7 @@
$: update(calendars) $: update(calendars)
$: all = getAllEvents(raw, from, to) $: all = getAllEvents(raw, from, to)
$: objects = hidePrivateEvents(all, $calendarStore) $: objects = hidePrivateEvents(all, $calendarByIdStore)
function inc (val: number): void { function inc (val: number): void {
if (val === 0) { if (val === 0) {
@ -140,7 +140,7 @@
} }
raw = raw raw = raw
all = getAllEvents(raw, from, to) all = getAllEvents(raw, from, to)
objects = hidePrivateEvents(all, $calendarStore) objects = hidePrivateEvents(all, $calendarByIdStore)
} }
} }
function dragLeave (event: DragEvent) { function dragLeave (event: DragEvent) {
@ -155,7 +155,7 @@
if (dragItem === null) { if (dragItem === null) {
raw = raw.filter((p) => p._id !== dragItemId) raw = raw.filter((p) => p._id !== dragItemId)
all = getAllEvents(raw, from, to) all = getAllEvents(raw, from, to)
objects = hidePrivateEvents(all, $calendarStore) objects = hidePrivateEvents(all, $calendarByIdStore)
} }
} }
$: clear(dragItem) $: clear(dragItem)

View File

@ -14,7 +14,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import calendar, { Calendar, Event } from '@hcengineering/calendar' import calendar, { Calendar, Event } from '@hcengineering/calendar'
import { calendarStore, hidePrivateEvents } from '@hcengineering/calendar-resources' import { visibleCalendarStore, hidePrivateEvents, calendarByIdStore } from '@hcengineering/calendar-resources'
import contact, { Person, PersonAccount } from '@hcengineering/contact' import contact, { Person, PersonAccount } from '@hcengineering/contact'
import { IdMap, Ref, toIdMap } from '@hcengineering/core' import { IdMap, Ref, toIdMap } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation' import { createQuery, getClient } from '@hcengineering/presentation'
@ -25,7 +25,6 @@
export let fromDate: number export let fromDate: number
export let toDate: number export let toDate: number
export let project: Project | undefined export let project: Project | undefined
export let calendars: IdMap<Calendar> = new Map()
export let personAccounts: PersonAccount[] = [] export let personAccounts: PersonAccount[] = []
export let slots: WorkSlot[] = [] export let slots: WorkSlot[] = []
export let events: Event[] = [] export let events: Event[] = []
@ -78,9 +77,9 @@
} }
) )
$: raw = rawEvent.concat(rawReq) $: raw = rawEvent.concat(rawReq).filter((it, idx, arr) => arr.findIndex((e) => e.eventId === it.eventId) === idx)
$: visible = hidePrivateEvents(raw, $calendarStore, false) $: visible = hidePrivateEvents(raw, $calendarByIdStore, false)
const todoQuery = createQuery() const todoQuery = createQuery()
@ -97,11 +96,7 @@
} }
) )
const calendarQuery = createQuery() $: calendarIds = $visibleCalendarStore.map((p) => p._id)
$: calendarQuery.query(calendar.class.Calendar, { hidden: false }, (res) => {
calendarIds = res.map((p) => p._id)
calendars = toIdMap(res)
})
const personMapQuery = createQuery() const personMapQuery = createQuery()
$: personMapQuery.query(contact.class.PersonAccount, { person: { $in: persons } }, (res) => { $: personMapQuery.query(contact.class.PersonAccount, { person: { $in: persons } }, (res) => {

View File

@ -1,14 +1,14 @@
<script lang="ts"> <script lang="ts">
import { Calendar, Event, getAllEvents } from '@hcengineering/calendar' import { Event, getAllEvents } from '@hcengineering/calendar'
import { Person, PersonAccount } from '@hcengineering/contact'
import { IdMap, Ref } from '@hcengineering/core' import { IdMap, Ref } from '@hcengineering/core'
import { Project } from '@hcengineering/task' import { Project } from '@hcengineering/task'
import Border from '../../Border.svelte'
import WithTeamData from '../WithTeamData.svelte'
import DayPlan from './DayPlan.svelte'
import { toSlots } from '../utils'
import { Person, PersonAccount } from '@hcengineering/contact'
import { ToDo, WorkSlot } from '@hcengineering/time' import { ToDo, WorkSlot } from '@hcengineering/time'
import Border from '../../Border.svelte'
import Header from '../../Header.svelte' import Header from '../../Header.svelte'
import WithTeamData from '../WithTeamData.svelte'
import { toSlots } from '../utils'
import DayPlan from './DayPlan.svelte'
export let space: Ref<Project> export let space: Ref<Project>
export let currentDate: Date export let currentDate: Date
@ -22,7 +22,6 @@
$: todayTo = new Date(tomorrow).setHours(0, 0, 0, 0) $: todayTo = new Date(tomorrow).setHours(0, 0, 0, 0)
let project: Project | undefined let project: Project | undefined
let calendars: IdMap<Calendar> = new Map()
let personAccounts: PersonAccount[] = [] let personAccounts: PersonAccount[] = []
let slots: WorkSlot[] = [] let slots: WorkSlot[] = []
let events: Event[] = [] let events: Event[] = []
@ -47,7 +46,6 @@
fromDate={yesterdayFrom} fromDate={yesterdayFrom}
toDate={todayTo} toDate={todayTo}
bind:project bind:project
bind:calendars
bind:personAccounts bind:personAccounts
bind:todos bind:todos
bind:slots bind:slots
@ -67,7 +65,6 @@
{persons} {persons}
{personAccounts} {personAccounts}
{project} {project}
{calendars}
{todos} {todos}
/> />
</div> </div>
@ -83,7 +80,6 @@
{persons} {persons}
{personAccounts} {personAccounts}
{project} {project}
{calendars}
{todos} {todos}
/> />
</div> </div>

View File

@ -1,11 +1,11 @@
<script lang="ts"> <script lang="ts">
import { Calendar, Event } from '@hcengineering/calendar' import { Event } from '@hcengineering/calendar'
import { Person, PersonAccount } from '@hcengineering/contact' import { Person, PersonAccount } from '@hcengineering/contact'
import { IdMap, Ref, Timestamp } from '@hcengineering/core' import { IdMap, Ref, Timestamp } from '@hcengineering/core'
import { IntlString, getEmbeddedLabel } from '@hcengineering/platform' import { IntlString, getEmbeddedLabel } from '@hcengineering/platform'
import { Project } from '@hcengineering/task' import { Project } from '@hcengineering/task'
import { Label, Scroller, areDatesEqual, ticker } from '@hcengineering/ui'
import { ToDo, WorkSlot } from '@hcengineering/time' import { ToDo, WorkSlot } from '@hcengineering/time'
import { Label, Scroller, areDatesEqual, ticker } from '@hcengineering/ui'
import time from '../../../plugin' import time from '../../../plugin'
import PlanGroup from './PlanGroup.svelte' import PlanGroup from './PlanGroup.svelte'
@ -15,7 +15,6 @@
export let showAssignee: boolean = false export let showAssignee: boolean = false
export let persons: Ref<Person>[] export let persons: Ref<Person>[]
export let personAccounts: PersonAccount[] export let personAccounts: PersonAccount[]
export let calendars: IdMap<Calendar>
export let project: Project export let project: Project
export let todos: IdMap<ToDo> export let todos: IdMap<ToDo>
@ -44,6 +43,6 @@
</div> </div>
<Scroller padding={'0 1rem'} noStretch shrink> <Scroller padding={'0 1rem'} noStretch shrink>
<PlanGroup {slots} {events} {showAssignee} {personAccounts} {calendars} {todos} /> <PlanGroup {slots} {events} {showAssignee} {personAccounts} {todos} />
</Scroller> </Scroller>
<div class="antiVSpacer x4" /> <div class="antiVSpacer x4" />

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Calendar, Event } from '@hcengineering/calendar' import { Event } from '@hcengineering/calendar'
import { calendarStore } from '@hcengineering/calendar-resources' import { calendarByIdStore } from '@hcengineering/calendar-resources'
import { PersonAccount } from '@hcengineering/contact' import { PersonAccount } from '@hcengineering/contact'
import { IdMap, getCurrentAccount } from '@hcengineering/core' import { IdMap, getCurrentAccount } from '@hcengineering/core'
import { ToDo, WorkSlot } from '@hcengineering/time' import { ToDo, WorkSlot } from '@hcengineering/time'
@ -12,12 +12,11 @@
export let showAssignee: boolean = false export let showAssignee: boolean = false
export let personAccounts: PersonAccount[] export let personAccounts: PersonAccount[]
export let calendars: IdMap<Calendar>
export let todos: IdMap<ToDo> export let todos: IdMap<ToDo>
const me = (getCurrentAccount() as PersonAccount).person const me = (getCurrentAccount() as PersonAccount).person
$: grouped = groupTeamData(slots, todos, events, personAccounts, calendars, me, $calendarStore) $: grouped = groupTeamData(slots, todos, events, personAccounts, me, $calendarByIdStore)
</script> </script>
<div class="container flex-col background-comp-header-color"> <div class="container flex-col background-comp-header-color">

View File

@ -14,7 +14,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import calendar, { CalendarEventPresenter, Event } from '@hcengineering/calendar' import calendar, { CalendarEventPresenter, Event } from '@hcengineering/calendar'
import { EventPresenter, calendarStore, isVisible } from '@hcengineering/calendar-resources' import { EventPresenter, calendarByIdStore, isVisible } from '@hcengineering/calendar-resources'
import { Doc } from '@hcengineering/core' import { Doc } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation' import { getClient } from '@hcengineering/presentation'
import { Component, MILLISECONDS_IN_MINUTE, showPopup, tooltip } from '@hcengineering/ui' import { Component, MILLISECONDS_IN_MINUTE, showPopup, tooltip } from '@hcengineering/ui'
@ -47,7 +47,7 @@
let div: HTMLDivElement let div: HTMLDivElement
$: visible = isVisible(event, $calendarStore) $: visible = isVisible(event, $calendarByIdStore)
function onContext (e: MouseEvent): void { function onContext (e: MouseEvent): void {
showMenu(e, { object: event }) showMenu(e, { object: event })

View File

@ -13,8 +13,8 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import calendar, { Calendar, Event, getAllEvents } from '@hcengineering/calendar' import calendar, { Event, getAllEvents } from '@hcengineering/calendar'
import { calendarStore } from '@hcengineering/calendar-resources' import { calendarByIdStore } from '@hcengineering/calendar-resources'
import { Person, PersonAccount } from '@hcengineering/contact' import { Person, PersonAccount } from '@hcengineering/contact'
import core, { import core, {
Account, Account,
@ -32,9 +32,9 @@
import { Asset } from '@hcengineering/platform' import { Asset } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation' import { createQuery, getClient } from '@hcengineering/presentation'
import { Project } from '@hcengineering/task' import { Project } from '@hcengineering/task'
import { ToDo, WorkSlot } from '@hcengineering/time'
import { Icon, tooltip } from '@hcengineering/ui' import { Icon, tooltip } from '@hcengineering/ui'
import view from '@hcengineering/view' import view from '@hcengineering/view'
import { ToDo, WorkSlot } from '@hcengineering/time'
import time from '../../../plugin' import time from '../../../plugin'
import TimePresenter from '../../presenters/TimePresenter.svelte' import TimePresenter from '../../presenters/TimePresenter.svelte'
import WithTeamData from '../WithTeamData.svelte' import WithTeamData from '../WithTeamData.svelte'
@ -51,7 +51,6 @@
const me = (getCurrentAccount() as PersonAccount).person const me = (getCurrentAccount() as PersonAccount).person
let project: Project | undefined let project: Project | undefined
let calendars: IdMap<Calendar> = new Map()
let personAccounts: PersonAccount[] = [] let personAccounts: PersonAccount[] = []
let slots: WorkSlot[] = [] let slots: WorkSlot[] = []
let events: Event[] = [] let events: Event[] = []
@ -145,7 +144,6 @@
{fromDate} {fromDate}
{toDate} {toDate}
bind:project bind:project
bind:calendars
bind:personAccounts bind:personAccounts
bind:todos bind:todos
bind:slots bind:slots
@ -162,9 +160,8 @@
todos, todos,
getAllEvents(allEvents, dayFrom, dayTo), getAllEvents(allEvents, dayFrom, dayTo),
personAccounts, personAccounts,
calendars,
me, me,
$calendarStore $calendarByIdStore
)} )}
{@const gitem = grouped.find((it) => it.user === person)} {@const gitem = grouped.find((it) => it.user === person)}
{@const planned = gitem?.mappings.reduce((it, val) => it + val.total, 0) ?? 0} {@const planned = gitem?.mappings.reduce((it, val) => it + val.total, 0) ?? 0}

View File

@ -14,7 +14,7 @@
--> -->
<script lang="ts"> <script lang="ts">
import { Calendar, Event, getAllEvents } from '@hcengineering/calendar' import { Calendar, Event, getAllEvents } from '@hcengineering/calendar'
import { calendarStore } from '@hcengineering/calendar-resources' import { calendarByIdStore } from '@hcengineering/calendar-resources'
import { Person, PersonAccount } from '@hcengineering/contact' import { Person, PersonAccount } from '@hcengineering/contact'
import { IdMap, Ref, getCurrentAccount } from '@hcengineering/core' import { IdMap, Ref, getCurrentAccount } from '@hcengineering/core'
import { Project } from '@hcengineering/task' import { Project } from '@hcengineering/task'
@ -34,7 +34,6 @@
const me = (getCurrentAccount() as PersonAccount).person const me = (getCurrentAccount() as PersonAccount).person
let project: Project | undefined let project: Project | undefined
let calendars: IdMap<Calendar> = new Map()
let personAccounts: PersonAccount[] = [] let personAccounts: PersonAccount[] = []
let slots: WorkSlot[] = [] let slots: WorkSlot[] = []
let events: Event[] = [] let events: Event[] = []
@ -84,7 +83,6 @@
{fromDate} {fromDate}
{toDate} {toDate}
bind:project bind:project
bind:calendars
bind:personAccounts bind:personAccounts
bind:todos bind:todos
bind:slots bind:slots
@ -136,7 +134,7 @@
{@const dayTo = new Date(day).setHours(23, 59, 59, 999)} {@const dayTo = new Date(day).setHours(23, 59, 59, 999)}
{@const totalSlots = toSlots(getAllEvents(slots, dayFrom, dayTo))} {@const totalSlots = toSlots(getAllEvents(slots, dayFrom, dayTo))}
{@const totalEvents = getAllEvents(events, dayFrom, dayTo)} {@const totalEvents = getAllEvents(events, dayFrom, dayTo)}
{@const grouped = groupTeamData(totalSlots, todos, totalEvents, personAccounts, calendars, me, $calendarStore)} {@const grouped = groupTeamData(totalSlots, todos, totalEvents, personAccounts, me, $calendarByIdStore)}
{@const gitem = grouped.find((it) => it.user === person)} {@const gitem = grouped.find((it) => it.user === person)}
{@const hourWidths = calcHourWidth([...totalSlots, ...totalEvents], width)} {@const hourWidths = calcHourWidth([...totalSlots, ...totalEvents], width)}
{#if gitem} {#if gitem}

View File

@ -39,7 +39,6 @@ export function groupTeamData (
todos: IdMap<ToDo>, todos: IdMap<ToDo>,
events: Event[], events: Event[],
personAccounts: PersonAccount[], personAccounts: PersonAccount[],
calendars: IdMap<Calendar>,
mePerson: Ref<Person>, mePerson: Ref<Person>,
calendarStore: IdMap<Calendar> calendarStore: IdMap<Calendar>
): EventPersonMapping[] { ): EventPersonMapping[] {
@ -91,8 +90,8 @@ export function groupTeamData (
} }
for (const event of events) { for (const event of events) {
const _calendar = calendars.get(event.calendar) const _calendar = calendarStore.get(event.calendar)
if (_calendar === undefined) { if (_calendar === undefined || _calendar.hidden) {
continue continue
} }
for (const p of event.participants) { for (const p of event.participants) {
@ -126,12 +125,6 @@ export function groupTeamData (
} }
} }
} }
console.log(
Array.from(totalEventsMap.entries()).map(([k, it]) => [
k,
it.toSorted((a, b) => a.date - b.date).map((q) => [new Date(q.date), new Date(q.dueDate)])
])
)
return Array.from(result.values()) return Array.from(result.values())
} }