From 84b265cd54e8675232d023925f0d4dca8efdad9b Mon Sep 17 00:00:00 2001 From: Alex van Andel Date: Mon, 17 Feb 2025 19:39:20 +0000 Subject: [PATCH] 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 --- .../components/TeamAvailabilityTimes.tsx | 6 + packages/lib/slots.test.ts | 162 +----------------- packages/lib/slots.ts | 117 +------------ 3 files changed, 11 insertions(+), 274 deletions(-) diff --git a/packages/features/ee/teams/components/TeamAvailabilityTimes.tsx b/packages/features/ee/teams/components/TeamAvailabilityTimes.tsx index 9cbf873886..7478ef5f13 100644 --- a/packages/features/ee/teams/components/TeamAvailabilityTimes.tsx +++ b/packages/features/ee/teams/components/TeamAvailabilityTimes.tsx @@ -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"; diff --git a/packages/lib/slots.test.ts b/packages/lib/slots.test.ts index fef7171e79..f16ec9df4e 100644 --- a/packages/lib/slots.test.ts +++ b/packages/lib/slots.test.ts @@ -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({ diff --git a/packages/lib/slots.ts b/packages/lib/slots.ts index 0d6ad13537..3abe0bdd75 100644 --- a/packages/lib/slots.ts +++ b/packages/lib/slots.ts @@ -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;