diff --git a/__test__/features/Events/EventApi.test.tsx b/__test__/features/Events/EventApi.test.tsx
new file mode 100644
index 0000000..69b6a70
--- /dev/null
+++ b/__test__/features/Events/EventApi.test.tsx
@@ -0,0 +1,108 @@
+import {
+ putEvent,
+ moveEvent,
+ deleteEvent,
+} from "../../../src/features/Events/EventApi";
+import { calendarEventToJCal } from "../../../src/features/Events/eventUtils";
+import { clientConfig } from "../../../src/features/User/oidcAuth";
+import { api } from "../../../src/utils/apiUtils";
+clientConfig.url = "https://example.com";
+
+jest.mock("../../../src/utils/apiUtils");
+
+const day = new Date();
+
+const mockEvent = {
+ uid: "event1",
+ title: "Test Event",
+ timezone: "UTC",
+ calId: "667037022b752d0026472254/cal1",
+ URL: "/calendars/667037022b752d0026472254/667037022b752d0026472254/cal1.ics",
+ start: day,
+ end: day,
+ status: "PUBLIC",
+ organizer: { cn: "test", cal_address: "test@test.com" },
+ attendee: [
+ {
+ cn: "test",
+ cal_address: "test@test.com",
+ partstat: "NEEDS-ACTION",
+ rsvp: "TRUE",
+ role: "REQ-PARTICIPANT",
+ cutype: "INDIVIDUAL",
+ },
+ {
+ cn: "John",
+ cal_address: "john@test.com",
+ partstat: "NEEDS-ACTION",
+ rsvp: "TRUE",
+ role: "REQ-PARTICIPANT",
+ cutype: "INDIVIDUAL",
+ },
+ ],
+};
+
+describe("eventApi", () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ test("putEvent sends PUT request with JCal body", async () => {
+ const mockResponse = { status: 201, url: "/dav/cals/test.ics" };
+ (api as unknown as jest.Mock).mockReturnValue(mockResponse);
+ const result = await putEvent(mockEvent);
+ const expectedResult = calendarEventToJCal(mockEvent);
+ expect(api).toHaveBeenCalledWith(
+ "dav/calendars/667037022b752d0026472254/667037022b752d0026472254/cal1.ics",
+ expect.objectContaining({
+ method: "PUT",
+ headers: { "content-type": "text/calendar; charset=utf-8" },
+ body: JSON.stringify(expectedResult),
+ })
+ );
+ expect(result).toBe(mockResponse);
+ });
+
+ test("putEvent logs when status is 201", async () => {
+ const mockResponse = { status: 201, url: "/dav/cals/test.ics" };
+ (api as unknown as jest.Mock).mockReturnValue(mockResponse);
+ const logSpy = jest.spyOn(console, "log").mockImplementation(() => {});
+
+ await putEvent(mockEvent);
+ expect(logSpy).toHaveBeenCalledWith("PUT (201) :", "/dav/cals/test.ics");
+
+ logSpy.mockRestore();
+ });
+
+ test("moveEvent sends MOVE request with destination header", async () => {
+ const mockResponse = { status: 204 };
+ (api as unknown as jest.Mock).mockReturnValue({
+ json: jest.fn().mockResolvedValue(mockResponse),
+ });
+ const result = await moveEvent(mockEvent);
+
+ expect(api).toHaveBeenCalledWith(
+ "dav/calendars/667037022b752d0026472254/667037022b752d0026472254/cal1.ics",
+ expect.objectContaining({
+ method: "MOVE",
+ headers: {
+ destination:
+ "/calendars/667037022b752d0026472254/667037022b752d0026472254/cal1.ics",
+ },
+ })
+ );
+ });
+
+ test("deleteEvent sends DELETE request and returns json response", async () => {
+ const mockResponse = { ok: true };
+ (api as unknown as jest.Mock).mockReturnValue({
+ json: jest.fn().mockResolvedValue(mockResponse),
+ });
+
+ const result = await deleteEvent("/calendars/test.ics");
+
+ expect(api).toHaveBeenCalledWith("dav/calendars/test.ics", {
+ method: "DELETE",
+ });
+ });
+});
diff --git a/__test__/features/Events/EventDisplay.test.tsx b/__test__/features/Events/EventDisplay.test.tsx
index 8eb9e90..42190f4 100644
--- a/__test__/features/Events/EventDisplay.test.tsx
+++ b/__test__/features/Events/EventDisplay.test.tsx
@@ -1,13 +1,14 @@
import { screen, fireEvent, waitFor } from "@testing-library/react";
import * as eventThunks from "../../../src/features/Calendars/CalendarSlice";
import { renderWithProviders } from "../../utils/Renderwithproviders";
-import EventPopover from "../../../src/features/Events/EventModal";
-import { DateSelectArg } from "@fullcalendar/core";
-import preview from "jest-preview";
-import { formatDateToYYYYMMDDTHHMMSS } from "../../../src/utils/dateUtils";
+import EventDisplayModal, {
+ InfoRow,
+ stringAvatar,
+ stringToColor,
+} from "../../../src/features/Events/EventDisplay";
import EventPreviewModal from "../../../src/features/Events/EventDisplayPreview";
-describe("Event Display", () => {
+describe("Event Preview Display", () => {
const mockOnClose = jest.fn();
const day = new Date();
const RealDateToLocaleString = Date.prototype.toLocaleString;
@@ -109,7 +110,6 @@ describe("Event Display", () => {
const dayOfMonth = day.getDate().toString();
expect(screen.getByText("Test Event")).toBeInTheDocument();
- preview.debug();
expect(screen.getByText(new RegExp(weekday, "i"))).toBeInTheDocument();
expect(screen.getByText(new RegExp(month, "i"))).toBeInTheDocument();
expect(
@@ -475,3 +475,577 @@ describe("Event Display", () => {
expect(updatedEvent.attendee[0].partstat).toBe("DECLINED");
});
});
+
+describe("Event Full Display", () => {
+ const mockOnClose = jest.fn();
+ const day = new Date();
+ const RealDateToLocaleString = Date.prototype.toLocaleString;
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ const preloadedState = {
+ user: {
+ userData: {
+ sub: "test",
+ email: "test@test.com",
+ sid: "aiYbWZSk2g0F+LrQeD7Dg4QcUMR8R/zTZdZBiA7N6Ro",
+ openpaasId: "667037022b752d0026472254",
+ },
+ organiserData: {
+ cn: "test",
+ cal_address: "mailto:test@test.com",
+ },
+ },
+ calendars: {
+ list: {
+ "667037022b752d0026472254/cal1": {
+ id: "667037022b752d0026472254/cal1",
+ name: "First Calendar",
+ color: "#FF0000",
+ events: {
+ event1: {
+ id: "event1",
+ title: "Test Event",
+ calId: "667037022b752d0026472254/cal1",
+ start: day.toISOString(),
+ end: day.toISOString(),
+ organizer: { cn: "test", cal_address: "test@test.com" },
+ attendee: [
+ {
+ cn: "test",
+ cal_address: "test@test.com",
+ partstat: "NEEDS-ACTION",
+ rsvp: "TRUE",
+ role: "REQ-PARTICIPANT",
+ cutype: "INDIVIDUAL",
+ },
+ {
+ cn: "John",
+ cal_address: "john@test.com",
+ partstat: "NEEDS-ACTION",
+ rsvp: "TRUE",
+ role: "REQ-PARTICIPANT",
+ cutype: "INDIVIDUAL",
+ },
+ ],
+ },
+ },
+ },
+ "otherCal/cal": {
+ id: "otherCal/cal",
+ name: "Calendar 1",
+ color: "#FF0000",
+ events: {
+ event1: {
+ id: "event1",
+ calId: "otherCal/cal",
+ title: "Test Event Other cal",
+ start: day.toISOString(),
+ end: day.toISOString(),
+ organizer: { cn: "john", cal_address: "john@test.com" },
+ },
+ },
+ },
+ },
+ pending: false,
+ },
+ };
+
+ it("renders correctly event data", () => {
+ jest
+ .spyOn(Date.prototype, "toLocaleString")
+ .mockImplementation(function (
+ this: Date,
+ locales?: Intl.LocalesArgument,
+ options?: Intl.DateTimeFormatOptions | undefined
+ ): string {
+ return RealDateToLocaleString.call(this, "en-UK", options);
+ });
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ day.setHours(day.getHours() + 2);
+ const date = day.toISOString().slice(0, 16);
+
+ expect(screen.getByDisplayValue("Test Event")).toBeInTheDocument();
+ expect(
+ screen.getAllByDisplayValue(new RegExp(date, "i"))[0]
+ ).toBeInTheDocument();
+ expect(
+ screen.getAllByDisplayValue(new RegExp(date, "i")).length
+ ).toBeLessThanOrEqual(2);
+
+ expect(screen.getByText("First Calendar")).toBeInTheDocument();
+ });
+ it("calls onClose when Cancel clicked", () => {
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ fireEvent.click(screen.getAllByTestId("CloseIcon")[0]);
+
+ expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
+ });
+ it("Shows delete button only when calendar is own", () => {
+ // Renders the other cal event
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ expect(screen.queryByTestId("DeleteIcon")).not.toBeInTheDocument();
+ // Renders the personnal cal event
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ expect(screen.queryByTestId("DeleteIcon")).toBeInTheDocument();
+ });
+ it("calls delete when Delete clicked", async () => {
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ const spy = jest
+ .spyOn(eventThunks, "deleteEventAsync")
+ .mockImplementation((payload) => {
+ return () => Promise.resolve(payload) as any;
+ });
+
+ fireEvent.click(screen.getByTestId("DeleteIcon"));
+
+ await waitFor(() => {
+ expect(spy).toHaveBeenCalled();
+ });
+
+ const receivedPayload = spy.mock.calls[0][0];
+
+ expect(receivedPayload).toEqual({
+ calId: "667037022b752d0026472254/cal1",
+ eventId: "event1",
+ });
+
+ expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
+ });
+ it("renders RSVP buttons when user is an attendee", () => {
+ const rsvpStateIsOrga = {
+ ...preloadedState,
+ calendars: {
+ ...preloadedState.calendars,
+ list: {
+ ...preloadedState.calendars.list,
+ "667037022b752d0026472254/cal1": {
+ ...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
+ events: {
+ event1: {
+ ...preloadedState.calendars.list[
+ "667037022b752d0026472254/cal1"
+ ].events.event1,
+ attendee: [
+ {
+ cal_address: "test@test.com",
+ cn: "Test User",
+ partstat: "NEEDS-ACTION",
+ },
+ {
+ cal_address: "organizer@test.com",
+ cn: "Test Organizer",
+ partstat: "NEEDS-ACTION",
+ },
+ ],
+ organizer: {
+ cal_address: "organizer@test.com",
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ renderWithProviders(
+ ,
+ rsvpStateIsOrga
+ );
+
+ expect(screen.getByRole("button", { name: "Accept" })).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: "Maybe" })).toBeInTheDocument();
+ expect(screen.getByRole("button", { name: "Decline" })).toBeInTheDocument();
+ });
+ it("doesnt renders RSVP buttons when user isnt an attendee", () => {
+ const rsvpStateIsOrga = {
+ ...preloadedState,
+ calendars: {
+ ...preloadedState.calendars,
+ list: {
+ ...preloadedState.calendars.list,
+ "667037022b752d0026472254/cal1": {
+ ...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
+ events: {
+ event1: {
+ ...preloadedState.calendars.list[
+ "667037022b752d0026472254/cal1"
+ ].events.event1,
+ attendee: [
+ {
+ cal_address: "organizer@test.com",
+ cn: "Test Organizer",
+ partstat: "NEEDS-ACTION",
+ },
+ ],
+ organizer: {
+ cal_address: "organizer@test.com",
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ renderWithProviders(
+ ,
+ rsvpStateIsOrga
+ );
+
+ expect(
+ screen.queryByRole("button", { name: "Accept" })
+ ).not.toBeInTheDocument();
+ expect(
+ screen.queryByRole("button", { name: "Maybe" })
+ ).not.toBeInTheDocument();
+ expect(
+ screen.queryByRole("button", { name: "Decline" })
+ ).not.toBeInTheDocument();
+ });
+
+ it("handles RSVP Accept click", async () => {
+ const spy = jest
+ .spyOn(eventThunks, "putEventAsync")
+ .mockImplementation((payload) => {
+ return () => Promise.resolve(payload) as any;
+ });
+
+ const rsvpState = {
+ ...preloadedState,
+ calendars: {
+ ...preloadedState.calendars,
+ list: {
+ ...preloadedState.calendars.list,
+ "667037022b752d0026472254/cal1": {
+ ...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
+ events: {
+ event1: {
+ ...preloadedState.calendars.list[
+ "667037022b752d0026472254/cal1"
+ ].events.event1,
+ attendee: [
+ {
+ cal_address: "test@test.com",
+ cn: "Test User",
+ partstat: "NEEDS-ACTION",
+ },
+ ],
+ organizer: {
+ cal_address: "organizer@test.com",
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ renderWithProviders(
+ ,
+ rsvpState
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "Accept" }));
+
+ await waitFor(() => {
+ expect(spy).toHaveBeenCalled();
+ expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
+ });
+
+ const updatedEvent = spy.mock.calls[0][0].newEvent;
+ expect(updatedEvent.attendee[0].partstat).toBe("ACCEPTED");
+ });
+
+ it("handles RSVP Maybe click", async () => {
+ const spy = jest
+ .spyOn(eventThunks, "putEventAsync")
+ .mockImplementation((payload) => {
+ return () => Promise.resolve(payload) as any;
+ });
+
+ const rsvpState = {
+ ...preloadedState,
+ calendars: {
+ ...preloadedState.calendars,
+ list: {
+ ...preloadedState.calendars.list,
+ "667037022b752d0026472254/cal1": {
+ ...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
+ events: {
+ event1: {
+ ...preloadedState.calendars.list[
+ "667037022b752d0026472254/cal1"
+ ].events.event1,
+ attendee: [
+ {
+ cal_address: "test@test.com",
+ cn: "Test User",
+ partstat: "NEEDS-ACTION",
+ },
+ ],
+ organizer: {
+ cal_address: "organizer@test.com",
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ renderWithProviders(
+ ,
+ rsvpState
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "Maybe" }));
+
+ await waitFor(() => {
+ expect(spy).toHaveBeenCalled();
+ expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
+ });
+
+ const updatedEvent = spy.mock.calls[0][0].newEvent;
+ expect(updatedEvent.attendee[0].partstat).toBe("TENTATIVE");
+ });
+
+ it("handles RSVP Decline click", async () => {
+ const spy = jest
+ .spyOn(eventThunks, "putEventAsync")
+ .mockImplementation((payload) => {
+ return () => Promise.resolve(payload) as any;
+ });
+
+ const rsvpState = {
+ ...preloadedState,
+ calendars: {
+ ...preloadedState.calendars,
+ list: {
+ ...preloadedState.calendars.list,
+ "667037022b752d0026472254/cal1": {
+ ...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
+ events: {
+ event1: {
+ ...preloadedState.calendars.list[
+ "667037022b752d0026472254/cal1"
+ ].events.event1,
+ attendee: [
+ {
+ cal_address: "test@test.com",
+ cn: "Test User",
+ partstat: "NEEDS-ACTION",
+ },
+ ],
+ organizer: {
+ cal_address: "organizer@test.com",
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ renderWithProviders(
+ ,
+ rsvpState
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "Decline" }));
+
+ await waitFor(() => {
+ expect(spy).toHaveBeenCalled();
+ expect(mockOnClose).toHaveBeenCalledWith({}, "backdropClick");
+ });
+
+ const updatedEvent = spy.mock.calls[0][0].newEvent;
+ expect(updatedEvent.attendee[0].partstat).toBe("DECLINED");
+ });
+ test("toggle Show More reveals extra fields", () => {
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ fireEvent.click(screen.getByText("Show More"));
+ expect(screen.getByLabelText("Alarm")).toBeInTheDocument();
+ expect(screen.getByLabelText("Repetition")).toBeInTheDocument();
+ expect(screen.getByLabelText("Visibility")).toBeInTheDocument();
+ fireEvent.click(screen.getByText("Show Less"));
+ });
+
+ test("can edit title when user is organizer", () => {
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ const titleField = screen.getByLabelText("Title");
+ fireEvent.change(titleField, { target: { value: "New Title" } });
+ expect(screen.getByDisplayValue("New Title")).toBeInTheDocument();
+ });
+ test("calendar select is disabled when not organizer", () => {
+ const rsvpState = {
+ ...preloadedState,
+ calendars: {
+ ...preloadedState.calendars,
+ list: {
+ ...preloadedState.calendars.list,
+ "667037022b752d0026472254/cal1": {
+ ...preloadedState.calendars.list["667037022b752d0026472254/cal1"],
+ events: {
+ event1: {
+ ...preloadedState.calendars.list[
+ "667037022b752d0026472254/cal1"
+ ].events.event1,
+ attendee: [
+ {
+ cal_address: "test@test.com",
+ cn: "Test User",
+ partstat: "NEEDS-ACTION",
+ },
+ ],
+ organizer: {
+ cal_address: "organizer@test.com",
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+
+ renderWithProviders(
+ ,
+ rsvpState
+ );
+ expect(screen.getByLabelText("Calendar")).toHaveClass("Mui-disabled");
+ });
+ test("toggle all-day updates end date correctly", () => {
+ renderWithProviders(
+ ,
+ preloadedState
+ );
+ const allDayCheckbox = screen.getByLabelText("All day");
+ fireEvent.click(allDayCheckbox);
+ expect(allDayCheckbox).toBeChecked();
+ const date = day.toISOString().split("T")[0];
+
+ expect(
+ screen.getAllByDisplayValue(new RegExp(date, "i"))[0]
+ ).toBeInTheDocument();
+ });
+});
+
+describe("Helper functions", () => {
+ test("stringToColor generates consistent color", () => {
+ expect(stringToColor("Alice")).toMatch(/^#[0-9a-f]{6}$/);
+ expect(stringToColor("Alice")).toBe(stringToColor("Alice"));
+ });
+
+ test("stringAvatar returns correct props", () => {
+ const result = stringAvatar("Alice");
+ expect(result.children).toBe("A");
+ expect(result.sx.bgcolor).toMatch(/^#/);
+ });
+
+ test("InfoRow renders text and link if url is valid", () => {
+ renderWithProviders(
+ ico}
+ text="Meeting"
+ data="https://example.com"
+ />
+ );
+ expect(screen.getByText("Meeting").closest("a")).toHaveAttribute(
+ "href",
+ "https://example.com"
+ );
+ });
+});
diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts
index b7435e2..cdbbd4e 100644
--- a/src/features/Calendars/CalendarSlice.ts
+++ b/src/features/Calendars/CalendarSlice.ts
@@ -4,7 +4,7 @@ import { CalendarEvent } from "../Events/EventsTypes";
import { getCalendar, getCalendars } from "./CalendarApi";
import { getOpenPaasUser, getUserDetails } from "../User/userAPI";
import { parseCalendarEvent } from "../Events/eventUtils";
-import { deleteEvent, putEvent } from "../Events/EventApi";
+import { deleteEvent, moveEvent, putEvent } from "../Events/EventApi";
import { formatDateToYYYYMMDDTHHMMSS } from "../../utils/dateUtils";
export const getCalendarsListAsync = createAsyncThunk<
@@ -92,6 +92,32 @@ export const putEventAsync = createAsyncThunk<
events,
};
});
+export const moveEventAsync = createAsyncThunk<
+ { calId: string; events: CalendarEvent[] }, // Return type
+ { cal: Calendars; newEvent: CalendarEvent } // Arg type
+>("calendars/moveEvent", async ({ cal, newEvent }) => {
+ const response = await moveEvent(newEvent);
+ const calEvents = (await getCalendar(cal.id, {
+ start: formatDateToYYYYMMDDTHHMMSS(new Date(newEvent.start)),
+ end: formatDateToYYYYMMDDTHHMMSS(
+ new Date(new Date(newEvent.start).getTime() + 86400000)
+ ),
+ })) as Record;
+ const events: CalendarEvent[] = calEvents._embedded["dav:item"].flatMap(
+ (eventdata: any) => {
+ const vevents = eventdata.data[2] as any[][];
+ const eventURL = eventdata._links.self.href;
+ return vevents.map((vevent: any[]) => {
+ return parseCalendarEvent(vevent[1], cal.color ?? "", cal.id, eventURL);
+ });
+ }
+ );
+
+ return {
+ calId: cal.id,
+ events,
+ };
+});
export const deleteEventAsync = createAsyncThunk<
{ calId: string; eventId: string }, // Return type
@@ -207,6 +233,32 @@ const CalendarSlice = createSlice({
});
}
)
+ .addCase(
+ moveEventAsync.fulfilled,
+ (
+ state,
+ action: PayloadAction<{ calId: string; events: CalendarEvent[] }>
+ ) => {
+ state.pending = false;
+ if (!state.list[action.payload.calId]) {
+ state.list[action.payload.calId] = {
+ id: action.payload.calId,
+ events: {},
+ } as Calendars;
+ }
+ action.payload.events.forEach((event) => {
+ state.list[action.payload.calId].events[event.uid] = event;
+ });
+ Object.keys(state.list[action.payload.calId].events).forEach((id) => {
+ state.list[action.payload.calId].events[id].color =
+ state.list[action.payload.calId].color;
+ state.list[action.payload.calId].events[id].calId =
+ action.payload.calId;
+ state.list[action.payload.calId].events[id].timezone =
+ Intl.DateTimeFormat().resolvedOptions().timeZone;
+ });
+ }
+ )
.addCase(deleteEventAsync.fulfilled, (state, action) => {
state.pending = false;
delete state.list[action.payload.calId].events[action.payload.eventId];
@@ -220,6 +272,9 @@ const CalendarSlice = createSlice({
.addCase(putEventAsync.pending, (state) => {
state.pending = true;
})
+ .addCase(moveEventAsync.pending, (state) => {
+ state.pending = true;
+ })
.addCase(deleteEventAsync.pending, (state) => {
state.pending = true;
});
diff --git a/src/features/Events/EventApi.ts b/src/features/Events/EventApi.ts
index a288b77..018cf1e 100644
--- a/src/features/Events/EventApi.ts
+++ b/src/features/Events/EventApi.ts
@@ -16,9 +16,19 @@ export async function putEvent(event: CalendarEvent) {
return response;
}
+export async function moveEvent(event: CalendarEvent) {
+ const response = await api(`dav${event.URL}`, {
+ method: "MOVE",
+ headers: {
+ destination: event.URL,
+ },
+ });
+ return response;
+}
+
export async function deleteEvent(eventURL: string) {
const response = await api(`dav${eventURL}`, {
method: "DELETE",
- }).json();
+ });
return response;
}
diff --git a/src/features/Events/EventDisplay.tsx b/src/features/Events/EventDisplay.tsx
index 12940bb..ecf3bd6 100644
--- a/src/features/Events/EventDisplay.tsx
+++ b/src/features/Events/EventDisplay.tsx
@@ -1,5 +1,9 @@
import { useEffect, useState } from "react";
-import { deleteEventAsync, putEventAsync } from "../Calendars/CalendarSlice";
+import {
+ deleteEventAsync,
+ moveEventAsync,
+ putEventAsync,
+} from "../Calendars/CalendarSlice";
import { useAppDispatch, useAppSelector } from "../../app/hooks";
import AttendeeSelector from "../../components/Attendees/AttendeeSearch";
import {
@@ -86,7 +90,7 @@ export default function EventDisplayModal({
const [alarm, setAlarm] = useState("");
const [eventClass, setEventClass] = useState(event?.class ?? "PUBLIC");
const [timezone, setTimezone] = useState(event?.timezone ?? "UTC");
-
+ const [newCalId, setNewCalId] = useState(event.calId);
const [calendarid, setCalendarid] = useState(
event?.calId.split("/")[0] === user.userData.openpaasId
? userPersonnalCalendars.findIndex((cal) => cal.id === calId)
@@ -169,6 +173,12 @@ export default function EventDisplayModal({
newEvent,
})
);
+
+ if (newCalId !== calId) {
+ dispatch(
+ moveEventAsync({ cal: userPersonnalCalendars[calendarid], newEvent })
+ );
+ }
onClose({}, "backdropClick");
};
@@ -279,9 +289,11 @@ export default function EventDisplayModal({
labelId="calendar-select-label"
value={calendarid.toString()}
label="Calendar"
- onChange={(e: SelectChangeEvent) =>
- setCalendarid(Number(e.target.value))
- }
+ onChange={(e: SelectChangeEvent) => {
+ const newId = Number(e.target.value);
+ setCalendarid(newId);
+ setNewCalId(userPersonnalCalendars[newId].id);
+ }}
>
{calList}
@@ -325,11 +337,6 @@ export default function EventDisplayModal({
const endDate = new Date(end);
const startDate = new Date(start);
setAllDay(!allday);
- console.log(
- endDate.getDate() === startDate.getDate(),
- endDate.getDate(),
- startDate.getDate()
- );
if (endDate.getDate() === startDate.getDate()) {
endDate.setDate(startDate.getDate() + 1);
setEnd(formatLocalDateTime(endDate));
@@ -390,7 +397,6 @@ export default function EventDisplayModal({
onClick={() => {
const newAttendeesList = [...attendees];
setAttendees(newAttendeesList.splice(idx, 1));
- console.log(attendees, newAttendeesList);
}}
>
@@ -496,18 +502,19 @@ export default function EventDisplayModal({
- {
- onClose({}, "backdropClick");
- dispatch(
- deleteEventAsync({ calId, eventId, eventURL: event.URL })
- );
- }}
- >
-
-
-
+ {isOwn && (
+ {
+ onClose({}, "backdropClick");
+ dispatch(
+ deleteEventAsync({ calId, eventId, eventURL: event.URL })
+ );
+ }}
+ >
+
+
+ )}
diff --git a/src/features/Events/EventDisplayPreview.tsx b/src/features/Events/EventDisplayPreview.tsx
index 0d9f8f3..78581e1 100644
--- a/src/features/Events/EventDisplayPreview.tsx
+++ b/src/features/Events/EventDisplayPreview.tsx
@@ -324,13 +324,6 @@ function formatEnd(start: Date, end: Date, allday?: boolean) {
startDate.getDate() === endDate.getDate();
if (allday) {
- console.log(
- endDate.toLocaleDateString(undefined, {
- year: "numeric",
- month: "short",
- day: "numeric",
- })
- );
return sameDay
? null
: endDate.toLocaleDateString(undefined, {
diff --git a/src/features/Events/EventModal.tsx b/src/features/Events/EventModal.tsx
index a3d838a..9b3ff5e 100644
--- a/src/features/Events/EventModal.tsx
+++ b/src/features/Events/EventModal.tsx
@@ -233,14 +233,8 @@ function EventPopover({
const endDate = new Date(end);
const startDate = new Date(start);
setAllDay(!allday);
- console.log(
- endDate.getDate() === startDate.getDate(),
- endDate.getDate(),
- startDate.getDate()
- );
if (endDate.getDate() === startDate.getDate()) {
endDate.setDate(startDate.getDate() + 1);
- console.log("formatedd", formatLocalDateTime(endDate));
setEnd(formatLocalDateTime(endDate));
}
@@ -258,7 +252,6 @@ function EventPopover({
),
allDay: allday,
};
- console.log(newRange, selectedRange);
setSelectedRange(newRange);
}}
/>
diff --git a/src/features/Events/eventUtils.ts b/src/features/Events/eventUtils.ts
index 17ffa30..b604603 100644
--- a/src/features/Events/eventUtils.ts
+++ b/src/features/Events/eventUtils.ts
@@ -126,11 +126,6 @@ export function calendarEventToJCal(event: CalendarEvent): any[] {
];
if (event.end) {
- console.log(
- event.end,
- event.start,
- event.end.getTime() === event.start.getTime()
- );
if (event.allday && event.end.getTime() === event.start.getTime()) {
event.end.setDate(event.start.getDate() + 1);
}