[#142] prefill event creation for any way of creating (#226)

Co-authored-by: Camille Moussu <cmoussu@linagora.com>
This commit is contained in:
Camille Moussu
2025-10-21 14:12:08 +02:00
committed by GitHub
parent e99c56f03f
commit 89ea554b1f
5 changed files with 118 additions and 35 deletions
+70
View File
@@ -256,6 +256,10 @@ describe("calendar Availability search", () => {
sid: "mockSid",
openpaasId: "user1",
},
organiserData: {
cn: "test",
cal_address: "test@test.com",
},
tokens: { accessToken: "token" },
},
calendars: {
@@ -324,6 +328,72 @@ describe("calendar Availability search", () => {
expect(spy).not.toHaveBeenCalledWith();
});
it("open window with attendees filled after temp search on create event button click", async () => {
const spy = jest
.spyOn(eventThunks, "getTempCalendarsListAsync")
.mockImplementation((payload) => {
return () => Promise.resolve(payload) as any;
});
mockedSearchUsers.mockResolvedValue([
{
email: "newuser@example.com",
displayName: "New User",
avatarUrl: "image.png",
openpaasId: "1234567890",
},
]);
renderWithProviders(<CalendarTestWrapper />, preloadedState);
const input = screen.getByPlaceholderText(/start typing a name or email/i);
userEvent.type(input, "New");
const option = await screen.findByText("New User");
fireEvent.click(option);
expect(spy).toHaveBeenCalled();
fireEvent.click(screen.getByRole("button", { name: /create event/i }));
await waitFor(() => {
expect(screen.getAllByText(/Create Event/i)).toHaveLength(2);
expect(screen.getAllByText(/New User/i)).toHaveLength(2);
});
});
it("open window with attendees filled after temp search on enter in temp input", async () => {
const spy = jest
.spyOn(eventThunks, "getTempCalendarsListAsync")
.mockImplementation((payload) => {
return () => Promise.resolve(payload) as any;
});
mockedSearchUsers.mockResolvedValue([
{
email: "newuser@example.com",
displayName: "New User",
avatarUrl: "image.png",
openpaasId: "1234567890",
},
]);
renderWithProviders(<CalendarTestWrapper />, preloadedState);
const input = screen.getByPlaceholderText(/start typing a name or email/i);
userEvent.type(input, "New");
const option = await screen.findByText("New User");
fireEvent.click(option);
expect(spy).toHaveBeenCalled();
fireEvent.keyDown(input, { key: "Enter" });
await waitFor(() => {
expect(screen.getAllByText(/Create Event/i)).toHaveLength(2);
expect(screen.getAllByText(/New User/i)).toHaveLength(2);
});
});
it("BUGFIX: can untoggle all personnal calendars", () => {
renderWithProviders(<CalendarTestWrapper />, {
user: preloadedState.user,
+10 -11
View File
@@ -16,14 +16,11 @@ import {
} from "../../features/Calendars/CalendarSlice";
import ImportAlert from "../../features/Events/ImportAlert";
import {
computeStartOfTheWeek,
formatDateToYYYYMMDDTHHMMSS,
getCalendarRange,
} from "../../utils/dateUtils";
import { Calendars } from "../../features/Calendars/CalendarTypes";
import { push } from "redux-first-history";
import EventPreviewModal from "../../features/Events/EventDisplayPreview";
import { createSelector } from "@reduxjs/toolkit";
import AddIcon from "@mui/icons-material/Add";
import { TempCalendarsInput } from "./TempCalendarsInput";
import Button from "@mui/material/Button";
@@ -41,13 +38,8 @@ import { EventErrorHandler } from "../Error/EventErrorHandler";
import { EventErrorSnackbar } from "../Error/ErrorSnackbar";
import momentTimezonePlugin from "@fullcalendar/moment-timezone";
import { TimezoneSelector } from "./TimezoneSelector";
import { DateCalendar } from "@mui/x-date-pickers/DateCalendar";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import moment from "moment";
import { DayCalendarSkeleton } from "@mui/x-date-pickers/DayCalendarSkeleton";
import { PickersDay } from "@mui/x-date-pickers/PickersDay";
import { MiniCalendar } from "./MiniCalendar";
import { User } from "../Attendees/PeopleSearch";
interface CalendarAppProps {
calendarRef: React.RefObject<CalendarApi | null>;
@@ -224,6 +216,7 @@ export default function CalendarApp({
null
);
const [tempUsers, setTempUsers] = useState<User[]>([]);
const [tempEvent, setTempEvent] = useState<CalendarEvent>(
{} as CalendarEvent
);
@@ -245,6 +238,9 @@ export default function CalendarApp({
setSelectedEvent,
setAfterChoiceFunc,
setOpenEditModePopup,
tempUsers,
setTempEvent,
timezone,
});
// View handlers
@@ -300,10 +296,13 @@ export default function CalendarApp({
dottedEvents={dottedEvents}
/>
<TempCalendarsInput
setAnchorEl={setAnchorEl}
tempUsers={tempUsers}
setTempUsers={setTempUsers}
handleToggleEventPreview={() => {
eventHandlers.handleDateSelect(null as unknown as DateSelectArg);
}}
selectedCalendars={selectedCalendars}
setSelectedCalendars={setSelectedCalendars}
setTempEvent={setTempEvent}
/>
<div className="calendarList">
<CalendarSelection
+7 -24
View File
@@ -1,27 +1,27 @@
import { useState, useRef } from "react";
import { useRef } from "react";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import {
getTempCalendarsListAsync,
removeTempCal,
} from "../../features/Calendars/CalendarSlice";
import { Calendars } from "../../features/Calendars/CalendarTypes";
import { CalendarEvent } from "../../features/Events/EventsTypes";
import { User, PeopleSearch } from "../Attendees/PeopleSearch";
const requestControllers = new Map<string, AbortController>();
export function TempCalendarsInput({
setAnchorEl,
setTempEvent,
tempUsers,
setTempUsers,
handleToggleEventPreview,
selectedCalendars,
setSelectedCalendars,
}: {
setAnchorEl: Function;
setTempEvent: Function;
tempUsers: User[];
setTempUsers: (users: User[]) => void;
handleToggleEventPreview: () => void;
selectedCalendars: string[];
setSelectedCalendars: Function;
}) {
const [tempUsers, setTempUsers] = useState<User[]>([]);
const dispatch = useAppDispatch();
const tempcalendars =
useAppSelector((state) => state.calendars.templist) ?? {};
@@ -86,23 +86,6 @@ export function TempCalendarsInput({
}
};
const handleToggleEventPreview = () => {
const newEvent: CalendarEvent = {
title: "New Event",
attendee: tempUsers.map((u) => ({
cn: u.displayName,
cal_address: u.email,
partstat: "NEED-ACTION",
role: "REQ-PARTICIPANT",
rsvp: "TRUE",
cutype: "INDIVIDUAL",
})),
} as CalendarEvent;
setTempEvent(newEvent);
setAnchorEl(document.body);
};
return (
<PeopleSearch
objectTypes={["user"]}
@@ -15,6 +15,8 @@ import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils";
import { getEvent } from "../../../features/Events/EventApi";
import { refreshCalendars } from "../../Event/utils/eventUtils";
import { updateTempCalendar } from "../utils/calendarUtils";
import { User } from "../../Attendees/PeopleSearch";
import { formatLocalDateTime } from "../../../features/Events/EventModal";
export interface EventHandlersProps {
setSelectedRange: (range: DateSelectArg | null) => void;
@@ -32,6 +34,9 @@ export interface EventHandlersProps {
setSelectedEvent: (event: CalendarEvent) => void;
setAfterChoiceFunc: (func: Function) => void;
setOpenEditModePopup: (open: string) => void;
tempUsers: User[];
setTempEvent: (event: CalendarEvent) => void;
timezone: string;
}
export const createEventHandlers = (props: EventHandlersProps) => {
@@ -51,10 +56,33 @@ export const createEventHandlers = (props: EventHandlersProps) => {
setSelectedEvent,
setAfterChoiceFunc,
setOpenEditModePopup,
tempUsers,
setTempEvent,
timezone,
} = props;
const handleDateSelect = (selectInfo: DateSelectArg) => {
setSelectedRange(selectInfo);
if (tempUsers) {
const newEvent: CalendarEvent = {
start: selectInfo?.start
? formatLocalDateTime(selectInfo?.start, timezone)
: "",
end: selectInfo?.end
? formatLocalDateTime(selectInfo?.end, timezone)
: "",
attendee: tempUsers.map((u) => ({
cn: u.displayName,
cal_address: u.email,
partstat: "NEED-ACTION",
role: "REQ-PARTICIPANT",
rsvp: "TRUE",
cutype: "INDIVIDUAL",
})),
} as CalendarEvent;
setTempEvent(newEvent);
}
setAnchorEl(document.body);
};
@@ -11,6 +11,9 @@ export const useCalendarEventHandlers = (props: EventHandlersProps) => {
handleDateSelect: useCallback(eventHandlers.handleDateSelect, [
props.setSelectedRange,
props.setAnchorEl,
props.setTempEvent,
props.tempUsers,
props.timezone,
]),
handleClosePopover: useCallback(eventHandlers.handleClosePopover, [
props.calendarRef,