Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions plugins/hr-resources/src/components/Schedule.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@

const query = createQuery()

let ancestors: Map<Ref<Department>, Ref<Department>[]> = new Map<Ref<Department>, Ref<Department>[]>()
let descendants: Map<Ref<Department>, Department[]> = new Map<Ref<Department>, Department[]>()
let departments: Map<Ref<Department>, Department> = new Map<Ref<Department>, Department>()

Expand All @@ -83,6 +84,9 @@
query.query(hr.class.Department, {}, (res) => {
departments.clear()
descendants.clear()
ancestors.clear()

// build descendants and departments
for (const doc of res) {
if (doc.parent !== undefined && doc._id !== hr.ids.Head) {
const current = descendants.get(doc.parent) ?? []
Expand All @@ -91,8 +95,28 @@
}
departments.set(doc._id, doc)
}

// build ancestors: for each department, walk up to root
const byId = new Map<Ref<Department>, Ref<Department>>()
for (const doc of res) {
byId.set(doc._id, doc.parent ?? hr.ids.Head)
}

for (const doc of res) {
const list: Ref<Department>[] = []
let parent: Ref<Department> | undefined = doc._id
while (parent !== undefined && parent !== hr.ids.Head) {
parent = byId.get(parent)
if (parent !== undefined) {
list.push(parent)
}
}
ancestors.set(doc._id, list)
}

departments = departments
descendants = descendants
ancestors = ancestors
})

function inc (val: number): void {
Expand Down Expand Up @@ -299,6 +323,7 @@
<ScheduleView
{department}
{descendants}
{ancestors}
departmentById={departments}
staffQuery={resultQuery}
{currentDate}
Expand Down
67 changes: 45 additions & 22 deletions plugins/hr-resources/src/components/ScheduleView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import { CalendarMode } from '@hcengineering/calendar-resources'
import { Employee, getCurrentEmployee } from '@hcengineering/contact'
import { DocumentQuery, Ref } from '@hcengineering/core'
import { Department, Request, RequestType, Staff, fromTzDate } from '@hcengineering/hr'
import { Department, PublicHoliday, Request, RequestType, Staff, fromTzDate } from '@hcengineering/hr'
import { createQuery, getClient } from '@hcengineering/presentation'
import tracker, { Issue } from '@hcengineering/tracker'
import { Label } from '@hcengineering/ui'
Expand All @@ -30,6 +30,7 @@

export let department: Ref<Department>
export let descendants: Map<Ref<Department>, Department[]>
export let ancestors: Map<Ref<Department>, Ref<Department>[]>
export let departmentById: Map<Ref<Department>, Department>
export let currentDate: Date = new Date()
export let mode: CalendarMode
Expand Down Expand Up @@ -232,7 +233,7 @@
}
}
)
let holidays = new Map<Ref<Department>, Date[]>()
let holidaysMap = new Map<Ref<Department>, Date[]>()
const holidaysQuery = createQuery()
$: holidaysQuery.query(
hr.class.PublicHoliday,
Expand All @@ -241,31 +242,33 @@
'date.year': currentDate.getFullYear()
},
(res) => {
const group = groupBy(res, 'department')
holidays = new Map()
for (const groupKey in group) {
holidays.set(
groupKey as Ref<Department>,
group[groupKey].map((holiday) => new Date(fromTzDate(holiday.date)))
)
}
holidaysMap = toHolidaysMap(res)
}
)

function toHolidaysMap (holidays: PublicHoliday[]): Map<Ref<Department>, Date[]> {
const group = groupBy(holidays, 'department')
const result = new Map()
for (const groupKey in group) {
// ensure unique holiday dates
const dates = new Set<number>()
for (const holiday of group[groupKey]) {
dates.add(fromTzDate(holiday.date))
}
result.set(
groupKey as Ref<Department>,
Array.from(dates).map((date) => new Date(date))
)
}
return result
}

async function getHolidays (month: Date): Promise<Map<Ref<Department>, Date[]>> {
const result = await client.findAll(hr.class.PublicHoliday, {
'date.month': month.getMonth(),
'date.year': month.getFullYear()
})
const group = groupBy(result, 'department')
const rMap = new Map()
for (const groupKey in group) {
rMap.set(
groupKey,
group[groupKey].map((holiday) => new Date(fromTzDate(holiday.date)))
)
}
return rMap
return toHolidaysMap(result)
}

const client = getClient()
Expand All @@ -285,15 +288,34 @@
return map
}
let staffDepartmentMap = new Map()
$: getDepartmentsForEmployee(departmentStaff).then((res) => {
$: void getDepartmentsForEmployee(departmentStaff).then((res) => {
staffDepartmentMap = res
})

function getDepartmentHolidays (department: Ref<Department>): Date[] {
const parents = ancestors.get(department) ?? []

const result = []

// get own holidays
const holidays = holidaysMap.get(department) ?? []
result.push(...holidays)

// get ancestor holidays
for (const parent of parents) {
const parentHolidays = holidaysMap.get(parent) ?? []
result.push(...parentHolidays)
}
return result
}
</script>

{#if staffDepartmentMap.size > 0}
{#if mode === CalendarMode.Year}
<YearView {departmentStaff} {employeeRequests} {types} {currentDate} {holidays} {staffDepartmentMap} />
<YearView {departmentStaff} {employeeRequests} {types} {currentDate} {holidaysMap} {staffDepartmentMap} />
{:else if mode === CalendarMode.Month}
{@const holidays = getDepartmentHolidays(department)}

{#if display === 'chart'}
<MonthView
{departmentStaff}
Expand All @@ -303,6 +325,7 @@
{editableList}
{currentDate}
{holidays}
{holidaysMap}
{department}
{departmentById}
{staffDepartmentMap}
Expand All @@ -314,7 +337,7 @@
{types}
{currentDate}
{timeReports}
{holidays}
{holidaysMap}
{staffDepartmentMap}
{getHolidays}
{preference}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,54 @@
import hr from '../../plugin'
import DepartmentEditor from '../DepartmentEditor.svelte'

let description: string
let title: string
export let date: Timestamp
export let department: Ref<Department>

const client = getClient()
let existingHoliday: PublicHoliday | undefined = undefined
const dispatch = createEventDispatcher()

async function findHoliday () {
existingHoliday = await client.findOne(hr.class.PublicHoliday, { date: timeToTzDate(date) })
let description: string
let title: string
let existingHoliday: PublicHoliday | undefined = undefined

async function getAncestors (department: Ref<Department>): Promise<Ref<Department>[]> {
const departments = await client.findAll(hr.class.Department, {})
const byId = new Map<Ref<Department>, Ref<Department>>()
for (const doc of departments) {
byId.set(doc._id, doc.parent ?? hr.ids.Head)
}

const ancestors: Ref<Department>[] = []
let parent: Ref<Department> | undefined = department
while (parent !== undefined && parent !== hr.ids.Head) {
parent = byId.get(parent)
if (parent !== undefined) {
ancestors.push(parent)
}
}
return ancestors
}

async function findHoliday (): Promise<void> {
const holidays = await client.findAll(hr.class.PublicHoliday, { date: timeToTzDate(date) })

// look into current department first
let holiday = holidays.find((p) => p.department === department)
if (holiday === undefined) {
// if not found look at parent departments
const ancestors = await getAncestors(department)
holiday = holidays.find((p) => ancestors.includes(p.department))
}

existingHoliday = holiday
if (existingHoliday !== undefined) {
title = existingHoliday.title
description = existingHoliday.description
department = existingHoliday.department
}
}

async function saveHoliday () {
async function saveHoliday (): Promise<void> {
if (existingHoliday !== undefined) {
await client.updateDoc(hr.class.PublicHoliday, core.space.Workspace, existingHoliday._id, {
title,
Expand All @@ -54,10 +84,16 @@
await client.createDoc(hr.class.PublicHoliday, core.space.Workspace, holiday)
}
}
findHoliday()

function deleteHoliday () {
existingHoliday && client.remove(existingHoliday)
let loading = true
void findHoliday().then(() => {
loading = false
})

function deleteHoliday (): void {
if (existingHoliday !== undefined) {
void client.remove(existingHoliday)
}
dispatch('close')
}
</script>
Expand All @@ -67,9 +103,9 @@
on:close
okLabel={existingHoliday ? presentation.string.Save : presentation.string.Ok}
okAction={() => {
saveHoliday()
void saveHoliday()
}}
canSave={true}
canSave={!loading}
on:changeContent
>
<div class="flex-grow mt-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
import { Doc, Ref } from '@hcengineering/core'
import type { Request, RequestType, Staff } from '@hcengineering/hr'
import { Department } from '@hcengineering/hr'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { Button, DropdownIntlItem, Label, Loading, showPopup, tableToCSV } from '@hcengineering/ui'
import { Label, Loading } from '@hcengineering/ui'
import { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
import { TableBrowser, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources'
import { TableBrowser } from '@hcengineering/view-resources'
import hr from '../../plugin'
import {
EmployeeReports,
Expand All @@ -47,7 +46,7 @@

export let employeeRequests: Map<Ref<Staff>, Request[]>
export let timeReports: Map<Ref<Employee>, EmployeeReports>
export let holidays: Map<Ref<Department>, Date[]> = new Map<Ref<Department>, Date[]>()
export let holidaysMap: Map<Ref<Department>, Date[]> = new Map<Ref<Department>, Date[]>()
export let getHolidays: (month: Date) => Promise<Map<Ref<Department>, Date[]>>
$: month = getStartDate(currentDate.getFullYear(), currentDate.getMonth()) // getMonth(currentDate, currentDate.getMonth())
$: wDays = weekDays(month.getFullYear(), month.getMonth())
Expand All @@ -60,7 +59,7 @@
types,
month.getFullYear(),
month.getMonth(),
getHolidayDatesForEmployee(staffDepartmentMap, staff._id, holidays)
getHolidayDatesForEmployee(staffDepartmentMap, staff._id, holidaysMap)
)
return ds.join(' ')
}
Expand Down
16 changes: 13 additions & 3 deletions plugins/hr-resources/src/components/schedule/MonthView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@
export let editableList: Ref<Employee>[]

export let staffDepartmentMap: Map<Ref<Staff>, Department[]>
export let holidays: Map<Ref<Department>, Date[]>

export let holidays: Date[]
export let holidaysMap: Map<Ref<Department>, Date[]>

const todayDate = new Date()

Expand Down Expand Up @@ -191,7 +193,7 @@
if (requests.length === 0) return
const weekend = isWeekend(day)
const holiday =
holidays?.size > 0 && isHoliday(getHolidayDatesForEmployee(staffDepartmentMap, staff._id, holidays), day)
holidaysMap?.size > 0 && isHoliday(getHolidayDatesForEmployee(staffDepartmentMap, staff._id, holidaysMap), day)
if (day && (weekend || holiday) && requests.some((req) => noWeekendHolidayType.includes(req.type))) {
return
}
Expand Down Expand Up @@ -307,6 +309,7 @@
{#each values as value}
{@const day = getDay(startDate, value)}
{@const today = areDatesEqual(todayDate, day)}
{@const holiday = isHoliday(holidays, day)}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
Expand All @@ -321,6 +324,7 @@
<div
class="timeline-day-header__day flex-col-center justify-center"
class:timeline-day-header__day--today={today}
class:timeline-day-header__day--holiday={holiday && !today}
>
{day.getDate()}
</div>
Expand Down Expand Up @@ -361,7 +365,7 @@
{@const today = areDatesEqual(todayDate, day)}
{@const weekend = isWeekend(day)}
{@const holiday = isHoliday(
getHolidayDatesForEmployee(staffDepartmentMap, employee._id, holidays),
getHolidayDatesForEmployee(staffDepartmentMap, employee._id, holidaysMap),
day
)}
{@const requests = getRequests(employeeRequests, day, day, employee._id)}
Expand Down Expand Up @@ -474,6 +478,12 @@
background-color: #3871e0;
border-radius: 0.375rem;
}

&.timeline-day-header__day--holiday {
color: white;
background-color: #d32f2f;
border-radius: 0.375rem;
}
}

.timeline-day-header__weekday {
Expand Down
6 changes: 3 additions & 3 deletions plugins/hr-resources/src/components/schedule/YearView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

export let employeeRequests: Map<Ref<Staff>, Request[]>

export let holidays: Map<Ref<Department>, Date[]>
export let holidaysMap: Map<Ref<Department>, Date[]>
export let staffDepartmentMap: Map<Ref<Staff>, Department[]>

function getTooltip (requests: Request[]): LabelAndProps | undefined {
Expand Down Expand Up @@ -117,7 +117,7 @@
startDate,
endDate,
types,
getHolidayDatesForEmployee(staffDepartmentMap, employee._id, holidays)
getHolidayDatesForEmployee(staffDepartmentMap, employee._id, holidaysMap)
)}
</div>
</td>
Expand All @@ -139,7 +139,7 @@
startDate,
endDate,
types,
[...holidays.values()].flat()
[...holidaysMap.values()].flat()
)}
</div>
</td>
Expand Down
Loading
Loading