@@ -135,7 +135,7 @@ describe("CalendarSelection", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
pending: false,
|
||||
pending: true,
|
||||
},
|
||||
};
|
||||
it("renders calendars", async () => {
|
||||
@@ -340,7 +340,7 @@ describe("calendar Availability search", () => {
|
||||
events: {},
|
||||
},
|
||||
},
|
||||
pending: false,
|
||||
pending: true,
|
||||
templist: {},
|
||||
},
|
||||
};
|
||||
@@ -495,12 +495,20 @@ describe("calendar Availability search", () => {
|
||||
}, 15000);
|
||||
|
||||
it("BUGFIX: can untoggle all calendar.personal", async () => {
|
||||
jest
|
||||
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
|
||||
.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
}) as any
|
||||
);
|
||||
await act(async () =>
|
||||
renderWithProviders(<CalendarTestWrapper />, {
|
||||
user: preloadedState.user,
|
||||
calendars: {
|
||||
list: { "user1/cal1": preloadedState.calendars.list["user1/cal1"] },
|
||||
pending: false,
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -572,8 +580,8 @@ describe("calendar Availability search", () => {
|
||||
calendarApi.changeView("dayGridMonth");
|
||||
fireEvent.click(screen.getByTestId("ChevronRightIcon"));
|
||||
});
|
||||
expect(spy).toHaveBeenCalledTimes(4);
|
||||
const callArgs = spy.mock.calls[3][0];
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
const callArgs = spy.mock.calls[1][0];
|
||||
expect(callArgs.calId).toBe("user1/cal1");
|
||||
|
||||
const startDate = new Date(
|
||||
@@ -621,10 +629,13 @@ describe("calendar Availability search", () => {
|
||||
|
||||
const spy = jest
|
||||
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
|
||||
.mockImplementation(() => ({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
})) as any;
|
||||
.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
}) as any
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
renderWithProviders(
|
||||
@@ -675,10 +686,13 @@ describe("calendar Availability search", () => {
|
||||
|
||||
const spy = jest
|
||||
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
|
||||
.mockImplementation(() => ({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
})) as any;
|
||||
.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
}) as any
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
renderWithProviders(
|
||||
@@ -708,10 +722,13 @@ describe("calendar Availability search", () => {
|
||||
it("does not make duplicate API calls for same calendar and range", async () => {
|
||||
const spy = jest
|
||||
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
|
||||
.mockImplementation(() => ({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
})) as any;
|
||||
.mockImplementation(
|
||||
() =>
|
||||
({
|
||||
type: "getCalendarDetailAsync",
|
||||
unwrap: () => Promise.resolve({}),
|
||||
}) as any
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
renderWithProviders(
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "@/utils/dateUtils";
|
||||
import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid";
|
||||
import { setSelectedCalendars as setSelectedCalendarsToStorage } from "@/utils/storage/setSelectedCalendars";
|
||||
import { useSelectedCalendars } from "@/utils/storage/useSelectedCalendars";
|
||||
import { browserDefaultTimeZone } from "@/utils/timezone";
|
||||
import { CalendarApi, DateSelectArg } from "@fullcalendar/core";
|
||||
import frLocale from "@fullcalendar/core/locales/fr";
|
||||
@@ -76,11 +77,14 @@ export default function CalendarApp({
|
||||
(state) => state.settings.hideDeclinedEvents
|
||||
);
|
||||
const calendars = useAppSelector((state) => state.calendars.list);
|
||||
const isPending = useAppSelector((state) => state.calendars.pending);
|
||||
const displayWeekNumbers = useAppSelector(
|
||||
(state) => state.settings.displayWeekNumbers
|
||||
);
|
||||
const tempcalendars = useAppSelector((state) => state.calendars.templist);
|
||||
const [selectedCalendars, setSelectedCalendars] = useState<string[]>([]);
|
||||
const storedCalendars = useSelectedCalendars();
|
||||
const [selectedCalendars, setSelectedCalendars] =
|
||||
useState<string[]>(storedCalendars);
|
||||
|
||||
const calendarLightSignature = useMemo(() => {
|
||||
return Object.values(calendars || {})
|
||||
@@ -253,6 +257,8 @@ export default function CalendarApp({
|
||||
}, [rangeKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPending) return;
|
||||
|
||||
if (!rangeKey || sortedSelectedCalendars.length === 0) {
|
||||
activeLoadCompletedRef.current = true;
|
||||
setActiveLoadCompleted(true);
|
||||
@@ -320,8 +326,7 @@ export default function CalendarApp({
|
||||
}, [dispatch, rangeKey, sortedSelectedCalendars, rangeStart, rangeEnd]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!rangeKey || !activeLoadCompleted) return;
|
||||
|
||||
if (!rangeKey || !activeLoadCompleted || isPending) return;
|
||||
const hiddenCalendars = calendarIds
|
||||
.filter((id) => !selectedCalendars.includes(id))
|
||||
.filter((id) => {
|
||||
@@ -355,6 +360,7 @@ export default function CalendarApp({
|
||||
rangeStart,
|
||||
rangeEnd,
|
||||
activeLoadCompleted,
|
||||
isPending,
|
||||
]);
|
||||
|
||||
const calendarsWithClearedCache = useMemo(() => {
|
||||
@@ -369,6 +375,7 @@ export default function CalendarApp({
|
||||
const processedCacheClearRef = useRef<Record<string, number>>({});
|
||||
|
||||
useEffect(() => {
|
||||
if (isPending) return;
|
||||
calendarsWithClearedCache.forEach(({ id, cleared }) => {
|
||||
if (processedCacheClearRef.current[id] === cleared) {
|
||||
return;
|
||||
@@ -397,7 +404,14 @@ export default function CalendarApp({
|
||||
prefetchedCalendarsRef.current[id] = "";
|
||||
});
|
||||
});
|
||||
}, [calendarsWithClearedCache, dispatch, rangeKey, rangeStart, rangeEnd]);
|
||||
}, [
|
||||
calendarsWithClearedCache,
|
||||
dispatch,
|
||||
rangeKey,
|
||||
rangeStart,
|
||||
rangeEnd,
|
||||
isPending,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const currentIds = new Set(tempCalendarIds);
|
||||
|
||||
@@ -28,7 +28,7 @@ const CalendarSlice = createSlice({
|
||||
initialState: {
|
||||
list: {} as Record<string, Calendar>,
|
||||
templist: {} as Record<string, Calendar>,
|
||||
pending: false,
|
||||
pending: true,
|
||||
error: null as string | null,
|
||||
} as {
|
||||
list: Record<string, Calendar>;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
|
||||
|
||||
export function useSelectedCalendars(): string[] {
|
||||
const [calendars, setCalendars] = useState<string[]>(() => {
|
||||
if (typeof window === "undefined") return [];
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem("selectedCalendars") ?? "[]");
|
||||
} catch {
|
||||
@@ -10,6 +11,8 @@ export function useSelectedCalendars(): string[] {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
const onStorage = (e: StorageEvent) => {
|
||||
if (e.key === "selectedCalendars") {
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,7 @@ export function WebSocketGate() {
|
||||
);
|
||||
|
||||
const [isSocketOpen, setIsSocketOpen] = useState(false);
|
||||
const isPending = useAppSelector((state) => state.calendars.pending);
|
||||
|
||||
const calendarList = useSelectedCalendars();
|
||||
const tempCalendarList = Object.keys(
|
||||
@@ -73,13 +74,15 @@ export function WebSocketGate() {
|
||||
|
||||
// Register using a diff with previous calendars
|
||||
useEffect(() => {
|
||||
if (isPending) return;
|
||||
|
||||
syncCalendarRegistrations(
|
||||
isSocketOpen,
|
||||
socketRef,
|
||||
calendarList,
|
||||
previousCalendarListRef
|
||||
);
|
||||
}, [isSocketOpen, calendarList]);
|
||||
}, [isSocketOpen, calendarList, isPending]);
|
||||
|
||||
useEffect(() => {
|
||||
syncCalendarRegistrations(
|
||||
|
||||
Reference in New Issue
Block a user