Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: show ooo forwarding and emoji when not available #18054

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
bd91268
feat: show ooo when not available
kart1ka Dec 7, 2024
ca2d3a9
fix: send correct username for toUser if user belongs to org
kart1ka Dec 7, 2024
5b0a2e7
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Dec 13, 2024
fcb2e05
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Dec 13, 2024
ab8c8cc
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
Udit-takkar Dec 16, 2024
7cc53a6
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Dec 20, 2024
8baeb00
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Dec 23, 2024
924c98f
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Dec 27, 2024
cfe3ba2
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Jan 1, 2025
69f89c1
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
anikdhabal Jan 4, 2025
8cea19f
enrich ooo user with profile in getUserAvailability
kart1ka Jan 6, 2025
77529c3
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Jan 7, 2025
8b6efe4
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Jan 14, 2025
b25dbb5
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Jan 15, 2025
8e8fb31
fix: set correct ooo slots
kart1ka Jan 15, 2025
fdb7184
Merge branch 'main' into feat/show-ooo-forwarding-and-emoji-when-not-…
kart1ka Jan 21, 2025
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
27 changes: 18 additions & 9 deletions packages/core/getUserAvailability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import { safeStringify } from "@calcom/lib/safeStringify";
import { EventTypeRepository } from "@calcom/lib/server/repository/eventType";
import { UserRepository } from "@calcom/lib/server/repository/user";
import prisma from "@calcom/prisma";
import { SchedulingType } from "@calcom/prisma/enums";
import { BookingStatus } from "@calcom/prisma/enums";
import { BookingStatus, SchedulingType } from "@calcom/prisma/enums";
import { EventTypeMetaDataSchema, stringToDayjsZod } from "@calcom/prisma/zod-utils";
import type { EventBusyDetails, IntervalLimitUnit } from "@calcom/types/Calendar";
import type { TimeRange } from "@calcom/types/schedule";
Expand Down Expand Up @@ -547,7 +546,7 @@ const _getUserAvailability = async function getUsersWorkingHoursLifeTheUniverseA
},
}));

const datesOutOfOffice: IOutOfOfficeData = calculateOutOfOfficeRanges(outOfOfficeDays, availability);
const datesOutOfOffice: IOutOfOfficeData = await calculateOutOfOfficeRanges(outOfOfficeDays, availability);

const { dateRanges, oooExcludedDateRanges } = buildDateRanges({
dateFrom,
Expand Down Expand Up @@ -636,15 +635,17 @@ export interface IOutOfOfficeData {
};
}

const calculateOutOfOfficeRanges = (
const calculateOutOfOfficeRanges = async (
outOfOfficeDays: GetUserAvailabilityInitialData["outOfOfficeDays"],
availability: GetUserAvailabilityParamsDTO["availability"]
): IOutOfOfficeData => {
): Promise<IOutOfOfficeData> => {
if (!outOfOfficeDays || outOfOfficeDays.length === 0) {
return {};
}

return outOfOfficeDays.reduce((acc: IOutOfOfficeData, { start, end, toUser, user, reason }) => {
const acc: IOutOfOfficeData = {};

for (const { start, end, toUser, user, reason } of outOfOfficeDays) {
// here we should use startDate or today if start is before today
// consider timezone in start and end date range
const startDateRange = dayjs(start).utc().isBefore(dayjs().startOf("day").utc())
Expand All @@ -665,19 +666,27 @@ const calculateOutOfOfficeRanges = (
continue; // Skip to the next iteration if day not found in flattenDays
}

const enrichedToUser = toUser ? await UserRepository.enrichUserWithItsProfile({ user: toUser }) : null;

acc[date.format("YYYY-MM-DD")] = {
// @TODO: would be good having start and end availability time here, but for now should be good
// you can obtain that from user availability defined outside of here
fromUser: { id: user.id, displayName: user.name },
// optional chaining destructuring toUser
toUser: !!toUser ? { id: toUser.id, displayName: toUser.name, username: toUser.username } : null,
...(!!enrichedToUser && {
toUser: {
id: enrichedToUser.id,
username: enrichedToUser.username,
displayName: enrichedToUser.name,
},
}),
reason: !!reason ? reason.reason : null,
emoji: !!reason ? reason.emoji : null,
};
}
}

return acc;
}, {});
return acc;
};

type GetUsersAvailabilityProps = {
Expand Down
22 changes: 21 additions & 1 deletion packages/lib/slots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ function buildSlotsWithDateRanges({
}
}

const processedOOODates = new Set<string>();
dateRanges.forEach((range) => {
const dateYYYYMMDD = range.start.format("YYYY-MM-DD");
const startTimeWithMinNotice = dayjs.utc().add(minimumBookingNotice, "minute");
Expand All @@ -206,6 +207,25 @@ function buildSlotsWithDateRanges({

slotStartTime = slotStartTime.add(offsetStart ?? 0, "minutes").tz(timeZone);

// Add OOO slot if exists and is before current range
if (datesOutOfOffice) {
Object.entries(datesOutOfOffice).forEach(([dateStr, oooData]) => {
const oooDate = dayjs(dateStr);
if (oooDate.isBefore(dateYYYYMMDD, "day") && !processedOOODates.has(dateStr)) {
slots.push({
time: oooDate.startOf("day"),
away: true,
...(oooData.fromUser && { fromUser: oooData.fromUser }),
...(oooData.toUser && { toUser: oooData.toUser }),
...(oooData.reason && { reason: oooData.reason }),
...(oooData.emoji && { emoji: oooData.emoji }),
});
// when the date range increases in the next iteration, we don't want to process this date again
processedOOODates.add(dateStr);
}
});
}

while (!slotStartTime.add(eventLength, "minutes").subtract(1, "second").utc().isAfter(rangeEnd)) {
const dateOutOfOfficeExists = datesOutOfOffice?.[dateYYYYMMDD];
let slotData: {
Expand All @@ -231,8 +251,8 @@ function buildSlotsWithDateRanges({
...(reason && { reason }),
...(emoji && { emoji }),
};
processedOOODates.add(dateYYYYMMDD);
}

slots.push(slotData);
slotStartTime = slotStartTime.add(frequency + (offsetStart ?? 0), "minutes");
}
Expand Down
Loading