refactor: Clean out old code, no longer needed (#19323)
* refactor: Clean out old code, no longer needed * Removed a sneaky one keen to stay behind
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
// @ts-nocheck
|
||||
|
||||
/* eslint-enable @typescript-eslint/ban-ts-comment */
|
||||
// TODO: Currently this file is not type checked as it's deprecated
|
||||
// it must be refactored if we want to restore TeamAvailability
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import type { ITimezone } from "react-timezone-select";
|
||||
|
||||
+3
-159
@@ -1,7 +1,6 @@
|
||||
import { describe, expect, it, beforeAll, vi } from "vitest";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { MINUTES_DAY_END, MINUTES_DAY_START } from "@calcom/lib/availability";
|
||||
|
||||
import type { DateRange } from "./date-ranges";
|
||||
import getSlots from "./slots";
|
||||
@@ -23,7 +22,7 @@ beforeAll(() => {
|
||||
];
|
||||
});
|
||||
|
||||
describe("Tests the date-range slot logic", () => {
|
||||
describe("Tests the slot logic", () => {
|
||||
it("can fit 24 hourly slots for an empty day", async () => {
|
||||
expect(
|
||||
getSlots({
|
||||
@@ -342,167 +341,12 @@ describe("Tests the date-range slot logic", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Tests the slot logic", () => {
|
||||
it("can fit 24 hourly slots for an empty day", async () => {
|
||||
// 24h in a day.
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs.utc().add(1, "day"),
|
||||
frequency: 60,
|
||||
minimumBookingNotice: 0,
|
||||
workingHours: [
|
||||
{
|
||||
userId: 1,
|
||||
days: Array.from(Array(7).keys()),
|
||||
startTime: MINUTES_DAY_START,
|
||||
endTime: MINUTES_DAY_END,
|
||||
},
|
||||
],
|
||||
eventLength: 60,
|
||||
offsetStart: 0,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(24);
|
||||
});
|
||||
|
||||
// TODO: This test is sound; it should pass!
|
||||
it("only shows future booking slots on the same day", async () => {
|
||||
// The mock date is 1s to midday, so 12 slots should be open given 0 booking notice.
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs.utc(),
|
||||
frequency: 60,
|
||||
minimumBookingNotice: 0,
|
||||
workingHours: [
|
||||
{
|
||||
userId: 1,
|
||||
days: Array.from(Array(7).keys()),
|
||||
startTime: MINUTES_DAY_START,
|
||||
endTime: MINUTES_DAY_END,
|
||||
},
|
||||
],
|
||||
eventLength: 60,
|
||||
offsetStart: 0,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(12);
|
||||
});
|
||||
|
||||
it("can cut off dates that due to invitee timezone differences fall on the next day", async () => {
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs().tz("Europe/Amsterdam").startOf("day"), // time translation +01:00
|
||||
frequency: 60,
|
||||
minimumBookingNotice: 0,
|
||||
workingHours: [
|
||||
{
|
||||
userId: 1,
|
||||
days: [0],
|
||||
startTime: 23 * 60, // 23h
|
||||
endTime: MINUTES_DAY_END,
|
||||
},
|
||||
],
|
||||
eventLength: 60,
|
||||
offsetStart: 0,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("can cut off dates that due to invitee timezone differences fall on the previous day", async () => {
|
||||
const workingHours = [
|
||||
{
|
||||
userId: 1,
|
||||
days: [0],
|
||||
startTime: MINUTES_DAY_START,
|
||||
endTime: 1 * 60, // 1h
|
||||
},
|
||||
];
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs().tz("Atlantic/Cape_Verde").startOf("day"), // time translation -01:00
|
||||
frequency: 60,
|
||||
minimumBookingNotice: 0,
|
||||
workingHours,
|
||||
eventLength: 60,
|
||||
offsetStart: 0,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("adds minimum booking notice correctly", async () => {
|
||||
// 24h in a day.
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs.utc().add(1, "day").startOf("day"),
|
||||
frequency: 60,
|
||||
minimumBookingNotice: 1500,
|
||||
workingHours: [
|
||||
{
|
||||
userId: 1,
|
||||
days: Array.from(Array(7).keys()),
|
||||
startTime: MINUTES_DAY_START,
|
||||
endTime: MINUTES_DAY_END,
|
||||
},
|
||||
],
|
||||
eventLength: 60,
|
||||
offsetStart: 0,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(11);
|
||||
});
|
||||
|
||||
it("can fit 48 25 minute slots with a 5 minute offset for an empty day", async () => {
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs.utc().add(1, "day"),
|
||||
frequency: 25,
|
||||
minimumBookingNotice: 0,
|
||||
workingHours: [
|
||||
{
|
||||
userId: 1,
|
||||
days: Array.from(Array(7).keys()),
|
||||
startTime: MINUTES_DAY_START,
|
||||
endTime: MINUTES_DAY_END,
|
||||
},
|
||||
],
|
||||
eventLength: 25,
|
||||
offsetStart: 5,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(48);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Tests the date-range slot logic with custom env variable", () => {
|
||||
describe("Tests the slot logic with custom env variable", () => {
|
||||
beforeAll(() => {
|
||||
vi.stubEnv("NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL", "10");
|
||||
});
|
||||
|
||||
it("can fit 11 10 minute slots within a 2 hour window using a 10 mintue availabilty option with a starting time of 10 past the hour", async () => {
|
||||
expect(Number(process.env.NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL)).toBe(10);
|
||||
expect(
|
||||
getSlots({
|
||||
inviteeDate: dayjs.utc().add(1, "day"),
|
||||
frequency: 10,
|
||||
minimumBookingNotice: 0,
|
||||
workingHours: [
|
||||
{
|
||||
userId: 1,
|
||||
days: Array.from(Array(7).keys()),
|
||||
startTime: 10,
|
||||
endTime: 120,
|
||||
},
|
||||
],
|
||||
eventLength: 10,
|
||||
offsetStart: 0,
|
||||
organizerTimeZone: "America/Toronto",
|
||||
})
|
||||
).toHaveLength(11);
|
||||
});
|
||||
|
||||
it("test buildSlotsWithDateRanges using a 10 mintue interval", async () => {
|
||||
it("test using a 10 minute interval", async () => {
|
||||
expect(Number(process.env.NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL)).toBe(10);
|
||||
expect(
|
||||
getSlots({
|
||||
|
||||
+2
-115
@@ -1,17 +1,13 @@
|
||||
import type { IFromUser, IOutOfOfficeData, IToUser } from "@calcom/core/getUserAvailability";
|
||||
import type { Dayjs } from "@calcom/dayjs";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import type { WorkingHours, TimeRange as DateOverride } from "@calcom/types/schedule";
|
||||
|
||||
import { getWorkingHours } from "./availability";
|
||||
import { getTimeZone } from "./date-fns";
|
||||
import type { DateRange } from "./date-ranges";
|
||||
|
||||
export type GetSlots = {
|
||||
inviteeDate: Dayjs;
|
||||
frequency: number;
|
||||
workingHours?: WorkingHours[];
|
||||
dateOverrides?: DateOverride[];
|
||||
dateRanges?: DateRange[];
|
||||
minimumBookingNotice: number;
|
||||
eventLength: number;
|
||||
@@ -373,8 +369,6 @@ const getSlots = ({
|
||||
inviteeDate,
|
||||
frequency,
|
||||
minimumBookingNotice,
|
||||
workingHours = [],
|
||||
dateOverrides = [],
|
||||
dateRanges,
|
||||
eventLength,
|
||||
offsetStart = 0,
|
||||
@@ -411,115 +405,8 @@ const getSlots = ({
|
||||
datesOutOfOffice,
|
||||
});
|
||||
}
|
||||
|
||||
if (!organizerTimeZone) {
|
||||
throw new Error("organizerTimeZone is required during getSlots call without dateRanges");
|
||||
}
|
||||
|
||||
// current date in invitee tz
|
||||
const startDate = dayjs().utcOffset(inviteeDate.utcOffset()).add(minimumBookingNotice, "minute");
|
||||
|
||||
// This code is ran client side, startOf() does some conversions based on the
|
||||
// local tz of the client. Sometimes this shifts the day incorrectly.
|
||||
const startOfDayUTC = dayjs.utc().set("hour", 0).set("minute", 0).set("second", 0);
|
||||
const startOfInviteeDay = inviteeDate.startOf("day");
|
||||
// checks if the start date is in the past
|
||||
|
||||
/**
|
||||
* TODO: change "day" for "hour" to stop displaying 1 day before today
|
||||
* This is displaying a day as available as sometimes difference between two dates is < 24 hrs.
|
||||
* But when doing timezones an available day for an owner can be 2 days available in other users tz.
|
||||
*
|
||||
* */
|
||||
if (inviteeDate.isBefore(startDate, "day")) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const timeZone: string = getTimeZone(inviteeDate);
|
||||
const workingHoursUTC = workingHours.map((schedule) => ({
|
||||
userId: schedule.userId,
|
||||
days: schedule.days,
|
||||
startTime: /* Why? */ startOfDayUTC.add(schedule.startTime, "minute"),
|
||||
endTime: /* Why? */ startOfDayUTC.add(schedule.endTime, "minute"),
|
||||
}));
|
||||
|
||||
const localWorkingHours = getWorkingHours(
|
||||
{
|
||||
// initialize current day with timeZone without conversion, just parse.
|
||||
utcOffset: -dayjs.tz(dayjs(), timeZone).utcOffset(),
|
||||
},
|
||||
workingHoursUTC
|
||||
).filter((hours) => hours.days.includes(inviteeDate.day()));
|
||||
|
||||
// Here we split working hour in chunks for every frequency available that can fit in whole working hours
|
||||
const computedLocalAvailability: TimeFrame[] = [];
|
||||
let tempComputeTimeFrame: TimeFrame | undefined;
|
||||
const computeLength = localWorkingHours.length - 1;
|
||||
const makeTimeFrame = (item: (typeof localWorkingHours)[0]): TimeFrame => ({
|
||||
userIds: item.userId ? [item.userId] : [],
|
||||
startTime: item.startTime,
|
||||
endTime: item.endTime,
|
||||
});
|
||||
|
||||
localWorkingHours.forEach((item, index) => {
|
||||
if (!tempComputeTimeFrame) {
|
||||
tempComputeTimeFrame = makeTimeFrame(item);
|
||||
} else {
|
||||
// please check the comment in splitAvailableTime func for the added 1 minute
|
||||
if (tempComputeTimeFrame.endTime + 1 === item.startTime) {
|
||||
// to deal with time that across the day, e.g. from 11:59 to to 12:01
|
||||
tempComputeTimeFrame.endTime = item.endTime;
|
||||
} else {
|
||||
computedLocalAvailability.push(tempComputeTimeFrame);
|
||||
tempComputeTimeFrame = makeTimeFrame(item);
|
||||
}
|
||||
}
|
||||
if (index == computeLength) {
|
||||
computedLocalAvailability.push(tempComputeTimeFrame);
|
||||
}
|
||||
});
|
||||
// an override precedes all the local working hour availability logic.
|
||||
const activeOverrides = dateOverrides.filter((override) => {
|
||||
return dayjs.utc(override.start).isBetween(startOfInviteeDay, startOfInviteeDay.endOf("day"), null, "[)");
|
||||
});
|
||||
|
||||
if (activeOverrides.length) {
|
||||
const overrides = activeOverrides.flatMap((override) => ({
|
||||
userIds: override.userId ? [override.userId] : [],
|
||||
startTime: override.start.getUTCHours() * 60 + override.start.getUTCMinutes(),
|
||||
endTime: override.end.getUTCHours() * 60 + override.end.getUTCMinutes(),
|
||||
}));
|
||||
// unset all working hours that relate to this user availability override
|
||||
overrides.forEach((override) => {
|
||||
let i = -1;
|
||||
const indexes: number[] = [];
|
||||
while (
|
||||
(i = computedLocalAvailability.findIndex(
|
||||
fromIndex(
|
||||
(a) => !a.userIds?.length || (!!override.userIds[0] && a.userIds?.includes(override.userIds[0])),
|
||||
i + 1
|
||||
)
|
||||
)) != -1
|
||||
) {
|
||||
indexes.push(i);
|
||||
}
|
||||
// work backwards as splice modifies the original array.
|
||||
indexes.reverse().forEach((idx) => computedLocalAvailability.splice(idx, 1));
|
||||
});
|
||||
// and push all overrides as new computed availability
|
||||
computedLocalAvailability.push(...overrides);
|
||||
}
|
||||
|
||||
return buildSlots({
|
||||
computedLocalAvailability,
|
||||
startOfInviteeDay,
|
||||
startDate,
|
||||
frequency,
|
||||
eventLength,
|
||||
offsetStart,
|
||||
organizerTimeZone,
|
||||
inviteeTimeZone: timeZone,
|
||||
});
|
||||
// just to ensure we don't call this anywhere. APIv1/v2 + webapp use dateRanges.
|
||||
throw new Error("Deprecated invocation of getSlots, use dateRanges instead.");
|
||||
};
|
||||
|
||||
export default getSlots;
|
||||
|
||||
Reference in New Issue
Block a user