Skip to content

Commit

Permalink
Schedule year view (#2145)
Browse files Browse the repository at this point in the history
Signed-off-by: Denis Bykhov <[email protected]>
  • Loading branch information
BykhovDenis authored Jun 25, 2022
1 parent 4f8b470 commit a74ae0e
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 49 deletions.
1 change: 1 addition & 0 deletions plugins/hr-resources/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@anticrm/platform": "~0.6.6",
"svelte": "^3.47",
"@anticrm/calendar": "~0.6.0",
"@anticrm/calendar-resources": "~0.6.0",
"@anticrm/hr": "~0.6.0",
"@anticrm/ui": "~0.6.0",
"@anticrm/presentation": "~0.6.2",
Expand Down
6 changes: 5 additions & 1 deletion plugins/hr-resources/src/components/CreateRequest.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
}
})
$: value = new Date(date).getTime()
let value = new Date(date).getTime()
$: dueDate = new Date(value).setDate(new Date(value).getDate() + 1)
export function canClose (): boolean {
Expand All @@ -72,6 +72,10 @@
function typeSelected (_id: Ref<RequestType>): void {
type = types.find((p) => p._id === _id)
dueDate =
Math.abs(type?.value ?? 0 % 1) === 0.5
? new Date(value).setHours(12)
: new Date(value).setDate(new Date(value).getDate() + 1)
}
</script>

Expand Down
5 changes: 2 additions & 3 deletions plugins/hr-resources/src/components/RequestsPopup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@
import { Table } from '@anticrm/view-resources'
export let date: Date
export let endDate: number
export let employee: Ref<Staff>
$: endDate = new Date(date).setDate(date.getDate() + 1)
</script>

<Table
_class={hr.class.Request}
query={{
attachedTo: employee,
dueDate: { $gte: date.getTime() },
dueDate: { $gt: date.getTime() },
date: { $lt: endDate }
}}
config={['$lookup.type.label', 'date', 'dueDate']}
Expand Down
64 changes: 47 additions & 17 deletions plugins/hr-resources/src/components/Schedule.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
// limitations under the License.
-->
<script lang="ts">
import calendar from '@anticrm/calendar'
import calendar from '@anticrm/calendar-resources/src/plugin'
import { CalendarMode } from '@anticrm/calendar-resources'
import { Ref } from '@anticrm/core'
import { Department } from '@anticrm/hr'
import { createQuery, SpaceSelector } from '@anticrm/presentation'
import { Button, Icon, IconBack, IconForward, Label } from '@anticrm/ui'
import hr from '../plugin'
import ScheduleView from './ScheduleView.svelte'
import ScheduleMonthView from './ScheduleView.svelte'
let department = hr.ids.Head
let currentDate: Date = new Date()
Expand All @@ -29,6 +30,8 @@
let descendants: Map<Ref<Department>, Department[]> = new Map<Ref<Department>, Department[]>()
let departments: Map<Ref<Department>, Department> = new Map<Ref<Department>, Department>()
let mode: CalendarMode = CalendarMode.Month
query.query(hr.class.Department, {}, (res) => {
departments.clear()
descendants.clear()
Expand All @@ -43,7 +46,16 @@
})
function inc (val: number): void {
currentDate.setMonth(currentDate.getMonth() + val)
switch (mode) {
case CalendarMode.Month: {
currentDate.setMonth(currentDate.getMonth() + val)
break
}
case CalendarMode.Year: {
currentDate.setFullYear(currentDate.getFullYear() + val)
break
}
}
currentDate = currentDate
}
Expand All @@ -58,37 +70,55 @@
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={calendar.icon.Calendar} size={'small'} /></div>
<span class="ac-header__title"><Label label={hr.string.Schedule} /></span>
<div class="flex ml-4 gap-2">
<Button
icon={IconBack}
size={'small'}
on:click={() => {
inc(-1)
}}
/>
<div class="flex gap-2 ml-6">
<Button
size={'small'}
label={hr.string.Today}
label={calendar.string.ModeMonth}
on:click={() => {
currentDate = new Date()
mode = CalendarMode.Month
}}
/>
<Button
icon={IconForward}
size={'small'}
label={calendar.string.ModeYear}
on:click={() => {
inc(1)
mode = CalendarMode.Year
}}
/>
<div class="flex ml-4 gap-2">
<Button
icon={IconBack}
size={'small'}
on:click={() => {
inc(-1)
}}
/>
<Button
size={'small'}
label={calendar.string.Today}
on:click={() => {
currentDate = new Date()
}}
/>
<Button
icon={IconForward}
size={'small'}
on:click={() => {
inc(1)
}}
/>
</div>
</div>
<div class="fs-title ml-4 flex-row-center">
{getMonthName(currentDate)}
{#if mode === CalendarMode.Month}
{getMonthName(currentDate)}
{/if}
{currentDate.getFullYear()}
</div>
</div>
<SpaceSelector _class={hr.class.Department} label={hr.string.Department} bind:space={department} />
</div>

<div class="mr-6 h-full">
<ScheduleView {department} {descendants} departmentById={departments} {currentDate} />
<ScheduleMonthView {department} {descendants} departmentById={departments} {currentDate} {mode} />
</div>
133 changes: 105 additions & 28 deletions plugins/hr-resources/src/components/ScheduleView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
-->
<script lang="ts">
import { getCurrentAccount, Ref, Timestamp } from '@anticrm/core'
import type { Department, Request, Staff } from '@anticrm/hr'
import type { Department, Request, RequestType, Staff } from '@anticrm/hr'
import { createQuery } from '@anticrm/presentation'
import {
Label,
Expand All @@ -30,6 +30,7 @@
LabelAndProps
} from '@anticrm/ui'
import { EmployeePresenter } from '@anticrm/contact-resources'
import { CalendarMode } from '@anticrm/calendar-resources'
import contact from '@anticrm/contact-resources/src/plugin'
import hr from '../plugin'
import { Employee, EmployeeAccount } from '@anticrm/contact'
Expand All @@ -41,14 +42,30 @@
export let descendants: Map<Ref<Department>, Department[]>
export let departmentById: Map<Ref<Department>, Department>
export let currentDate: Date = new Date()
export let mode: CalendarMode
$: startDate = new Date(new Date(currentDate).setDate(1)).setHours(0, 0, 0, 0)
$: endDate = new Date(startDate).setMonth(new Date(startDate).getMonth() + 1)
$: startDate = new Date(
new Date(mode === CalendarMode.Year ? new Date(currentDate).setMonth(1) : currentDate).setDate(1)
).setHours(0, 0, 0, 0)
$: endDate =
mode === CalendarMode.Year
? new Date(startDate).setFullYear(new Date(startDate).getFullYear() + 1)
: new Date(startDate).setMonth(new Date(startDate).getMonth() + 1)
$: departments = [department, ...getDescendants(department, descendants)]
const lq = createQuery()
const typeQuery = createQuery()
const staffQuery = createQuery()
let staff: Staff[] = []
let types: Map<Ref<RequestType>, RequestType> = new Map<Ref<RequestType>, RequestType>()
typeQuery.query(hr.class.RequestType, {}, (res) => {
types = new Map(
res.map((type) => {
return [type._id, type]
})
)
})
staffQuery.query(hr.mixin.Staff, {}, (res) => {
staff = res
Expand Down Expand Up @@ -96,7 +113,7 @@
if (requests === undefined) return []
const res: Request[] = []
const time = date.getTime()
const endTime = new Date(date).setDate(date.getDate() + 1)
const endTime = getEndDate(date)
for (const request of requests) {
if (request.date < endTime && request.dueDate > time) {
res.push(request)
Expand Down Expand Up @@ -134,16 +151,45 @@
return lead === currentEmployee
}
function getEndDate (date: Date): number {
return mode === CalendarMode.Year
? new Date(date).setMonth(date.getMonth() + 1)
: new Date(date).setDate(date.getDate() + 1)
}
function getTooltip (employee: Staff, date: Date): LabelAndProps | undefined {
const requests = getRequests(employee._id, date)
if (requests.length === 0) return
const endDate = getEndDate(date)
return {
component: RequestsPopup,
props: { date, employee: employee._id }
props: { date, endDate, employee: employee._id }
}
}
$: departmentStaff = staff.filter((p) => departments.includes(p.department) || employeeRequests.has(p._id))
$: values = [...Array(mode === CalendarMode.Year ? 12 : daysInMonth(currentDate)).keys()]
function getMonthName (date: Date): string {
return new Intl.DateTimeFormat('default', { month: 'long' }).format(date)
}
function getMonth (date: Date, m: number): Date {
date = new Date(date)
date.setDate(1)
date.setMonth(m)
return date
}
function getTotal (requests: Request[]): number {
let total = 0
for (const request of requests) {
const type = types.get(request.type)
const days = (request.dueDate - request.date) / 1000 / 60 / 60 / 24
total += Math.ceil(days) * (type?.value ?? 0)
}
return total
}
</script>

{#if departmentStaff.length}
Expand All @@ -154,14 +200,27 @@
<th>
<Label label={contact.string.Employee} />
</th>
{#each [...Array(daysInMonth(currentDate)).keys()] as dayOfMonth}
{@const day = getDay(new Date(startDate), dayOfMonth)}
<th class:today={areDatesEqual(todayDate, day)} class:weekend={isWeekend(day)}>
<div class="cursor-pointer uppercase flex-col-center">
<div class="flex-center">{getWeekDayName(day, 'short')}</div>
<div class="flex-center">{day.getDate()}</div>
</div>
</th>
{#each values as value}
{#if mode === CalendarMode.Year}
{@const month = getMonth(currentDate, value)}
<th
class="fixed"
class:today={month.getFullYear() === todayDate.getFullYear() &&
month.getMonth() === todayDate.getMonth()}
>
<div class="cursor-pointer uppercase flex-col-center">
<div class="flex-center">{getMonthName(month)}</div>
</div>
</th>
{:else}
{@const day = getDay(new Date(startDate), value)}
<th class:today={areDatesEqual(todayDate, day)} class:weekend={isWeekend(day)}>
<div class="cursor-pointer uppercase flex-col-center">
<div class="flex-center">{getWeekDayName(day, 'short')}</div>
<div class="flex-center">{day.getDate()}</div>
</div>
</th>
{/if}
{/each}
</tr>
</thead>
Expand All @@ -171,21 +230,36 @@
<td>
<EmployeePresenter value={employee} />
</td>
{#each [...Array(daysInMonth(currentDate)).keys()] as dayOfMonth}
{@const date = getDay(new Date(startDate), dayOfMonth)}
{@const requests = getRequests(employee._id, date)}
{@const editable = isEditable(employee)}
<td
class:today={areDatesEqual(todayDate, date)}
class:weekend={isWeekend(date)}
class:cursor-pointer={editable}
use:tooltip={getTooltip(employee, date)}
on:click={(e) => createRequest(e, date, employee)}
>
{#if requests.length}
<ScheduleRequests {requests} {date} {editable} />
{/if}
</td>
{#each values as value}
{#if mode === CalendarMode.Year}
{@const month = getMonth(currentDate, value)}
{@const requests = getRequests(employee._id, month)}
<td
class:today={month.getFullYear() === todayDate.getFullYear() &&
month.getMonth() === todayDate.getMonth()}
class="fixed"
use:tooltip={getTooltip(employee, month)}
>
<div class="flex-center">
{getTotal(requests)}
</div>
</td>
{:else}
{@const date = getDay(new Date(startDate), value)}
{@const requests = getRequests(employee._id, date)}
{@const editable = isEditable(employee)}
<td
class:today={areDatesEqual(todayDate, date)}
class:weekend={isWeekend(date)}
class:cursor-pointer={editable}
use:tooltip={getTooltip(employee, date)}
on:click={(e) => createRequest(e, date, employee)}
>
{#if requests.length}
<ScheduleRequests {requests} {date} {editable} />
{/if}
</td>
{/if}
{/each}
</tr>
{/each}
Expand All @@ -209,6 +283,9 @@
th {
width: auto;
min-width: 1rem;
&.fixed {
width: 5rem;
}
&:first-child {
width: 15rem;
padding: 0.5rem;
Expand Down

0 comments on commit a74ae0e

Please sign in to comment.