From d41cfe11863e08ab5447446976e80b43b22e12b4 Mon Sep 17 00:00:00 2001 From: Camille Moussu Date: Fri, 13 Mar 2026 14:45:29 +0100 Subject: [PATCH] [#625] only call freebusy for attendees that have neither accepted nor declined --- .../features/Events/EventDisplay.test.tsx | 12 ++++++++++-- src/components/Calendar/Calendar.tsx | 6 +++--- .../EventPreview/EventPreviewActionMenu.tsx | 4 +++- .../EventPreview/EventPreviewAttendees.tsx | 19 +++++++++---------- .../api/getFreeBusyForEventAttendeesPOST.ts | 5 ++++- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/__test__/features/Events/EventDisplay.test.tsx b/__test__/features/Events/EventDisplay.test.tsx index 7502b8b..f6cc215 100644 --- a/__test__/features/Events/EventDisplay.test.tsx +++ b/__test__/features/Events/EventDisplay.test.tsx @@ -652,7 +652,11 @@ describe("Event Preview Display", () => { const expectedUrl = `test/mailto/?uri=mailto%3Ajohn%40test.com&subject=Test%20Event`; - expect(mockOpen).toHaveBeenCalledWith(expectedUrl); + expect(mockOpen).toHaveBeenCalledWith( + expectedUrl, + "_blank", + "noopener,noreferrer" + ); }); it("message button encodes special characters in event title correctly", () => { @@ -723,7 +727,11 @@ describe("Event Preview Display", () => { const expectedUrl = `test/mailto/?uri=mailto%3Ajohn%40test.com&subject=Meeting%20%26%20Discussion%3F%20%23Important`; - expect(mockOpen).toHaveBeenCalledWith(expectedUrl); + expect(mockOpen).toHaveBeenCalledWith( + expectedUrl, + "_blank", + "noopener,noreferrer" + ); }); describe("Owner Email Permissions", () => { diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index fee6832..12077f9 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -40,9 +40,9 @@ import { TempCalendarsInput } from "./TempCalendarsInput"; import { TimezoneSelector } from "./TimezoneSelector"; import { updateDarkColor } from "./utils/calendarColorsUtils"; import { - eventToFullCalendarFormat, - extractEvents, - updateSlotLabelVisibility + eventToFullCalendarFormat, + extractEvents, + updateSlotLabelVisibility, } from "./utils/calendarUtils"; const localeMap: Record = { diff --git a/src/features/Events/EventPreview/EventPreviewActionMenu.tsx b/src/features/Events/EventPreview/EventPreviewActionMenu.tsx index ebf7523..3dbd284 100644 --- a/src/features/Events/EventPreview/EventPreviewActionMenu.tsx +++ b/src/features/Events/EventPreview/EventPreviewActionMenu.tsx @@ -38,7 +38,9 @@ export function EventPreviewActionMenu({ window.open( `${mailSpaUrl}/mailto/?uri=${encodeURIComponent( `mailto:${otherAttendees.map((a) => a.cal_address).join(",")}` - )}&subject=${encodeURIComponent(event.title ?? "")}` + )}&subject=${encodeURIComponent(event.title ?? "")}`, + "_blank", + "noopener,noreferrer" ) } > diff --git a/src/features/Events/EventPreview/EventPreviewAttendees.tsx b/src/features/Events/EventPreview/EventPreviewAttendees.tsx index 5deac66..2e68aa0 100644 --- a/src/features/Events/EventPreview/EventPreviewAttendees.tsx +++ b/src/features/Events/EventPreview/EventPreviewAttendees.tsx @@ -1,5 +1,6 @@ import { useAttendeesFreeBusy } from "@/components/Attendees/useFreeBusy"; import { renderAttendeeBadge } from "@/components/Event/utils/eventUtils"; +import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid"; import { AvatarGroup, Box, Typography } from "@linagora/twake-mui"; import PeopleAltOutlinedIcon from "@mui/icons-material/PeopleAltOutlined"; import { alpha, useTheme } from "@mui/material/styles"; @@ -44,12 +45,17 @@ export function EventPreviewAttendees({ }); const freeBusyMap = useAttendeesFreeBusy({ - existingAttendees: allAttendees.map(toFreeBusyAttendee), + existingAttendees: allAttendees + .filter( + (attendee) => + attendee.partstat !== "ACCEPTED" && attendee.partstat !== "DECLINED" + ) + .map(toFreeBusyAttendee), newAttendees: [], start: start ?? "", end: end ?? "", timezone: timezone ?? "UTC", - eventUid, + eventUid: extractEventBaseUuid(eventUid ?? ""), enabled: !!(start && end && showAllAttendees), }); @@ -107,14 +113,7 @@ export function EventPreviewAttendees({ {showAllAttendees && organizer && - renderAttendeeBadge( - organizer, - "org", - t, - showAllAttendees, - true, - busyCaption(organizer) - )} + renderAttendeeBadge(organizer, "org", t, showAllAttendees, true)} {showAllAttendees && attendees.map((a, idx) => renderAttendeeBadge( diff --git a/src/features/Events/api/getFreeBusyForEventAttendeesPOST.ts b/src/features/Events/api/getFreeBusyForEventAttendeesPOST.ts index 322a424..15da5f6 100644 --- a/src/features/Events/api/getFreeBusyForEventAttendeesPOST.ts +++ b/src/features/Events/api/getFreeBusyForEventAttendeesPOST.ts @@ -30,7 +30,10 @@ export async function getFreeBusyForEventAttendeesPOST( }); if (!r.ok) throw new Error(`HTTP ${r.status}`); - const { users } = (await r.json()) as { users: UserFreeBusy[] }; + const payload: unknown = await r.json(); + const users = Array.isArray((payload as { users?: unknown })?.users) + ? ((payload as { users: UserFreeBusy[] }).users ?? []) + : []; const eventUidBase = extractEventBaseUuid(eventUid);