From 8813bff48c268c03c6cc6c83fc69d867600db384 Mon Sep 17 00:00:00 2001 From: Camille Moussu <66134347+Eriikah@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:47:18 +0200 Subject: [PATCH] Calendar subscription naming (#235) Co-authored-by: Camille Moussu --- .../features/Calendars/CalendarAPI.test.tsx | 40 +++++++++++++++++ src/components/Calendar/Calendar.styl | 5 ++- src/components/Calendar/CalendarSearch.tsx | 6 ++- src/components/Calendar/CalendarSelection.tsx | 44 ++++++++++++++++--- src/features/Calendars/CalendarApi.ts | 4 ++ src/features/Calendars/CalendarSlice.ts | 18 ++++++-- 6 files changed, 106 insertions(+), 11 deletions(-) diff --git a/__test__/features/Calendars/CalendarAPI.test.tsx b/__test__/features/Calendars/CalendarAPI.test.tsx index 1acec9a..a8fd40b 100644 --- a/__test__/features/Calendars/CalendarAPI.test.tsx +++ b/__test__/features/Calendars/CalendarAPI.test.tsx @@ -1,6 +1,7 @@ // __test__/features/calendars/calendarApi.test.ts import { + addSharedCalendar, getCalendar, getCalendars, postCalendar, @@ -112,4 +113,43 @@ describe("Calendar API", () => { }, }); }); + + it("When adding a sharedCal with #default as a name a new name is sent to the back", async () => { + const mockApiPost = jest.spyOn(api, "post"); + + const calData = { + cal: { + id: "cal123", + "dav:name": "#default", + "apple:color": "#FF5733", + "caldav:description": "Default calendar", + acl: [], + invite: [], + _links: { + self: { + href: "/calendars/owner123/cal123.json", + }, + }, + }, + owner: { + displayName: "John Doe", + email: "john.doe@example.com", + openpaasId: "owner123", + }, + color: "#FF5733", + }; + + await addSharedCalendar("currentUserId", "newCalId123", calData); + + expect(mockApiPost).toHaveBeenCalledWith( + "dav/calendars/currentUserId.json", + expect.objectContaining({ + body: expect.stringContaining('"dav:name":"John Doe\'s calendar"'), + }) + ); + + const callBody = JSON.parse(String(mockApiPost.mock.calls[0][1]?.body)); + expect(callBody["dav:name"]).toBe("John Doe's calendar"); + expect(callBody["dav:name"]).not.toBe("#default"); + }); }); diff --git a/src/components/Calendar/Calendar.styl b/src/components/Calendar/Calendar.styl index 1ad1729..9515d2f 100644 --- a/src/components/Calendar/Calendar.styl +++ b/src/components/Calendar/Calendar.styl @@ -28,7 +28,10 @@ padding-left 5px height 100% flex-direction column - overflow auto + overflow-y: hidden + +.sidebar:hover + overflow-y: auto .declined-event opacity 0.7 diff --git a/src/components/Calendar/CalendarSearch.tsx b/src/components/Calendar/CalendarSearch.tsx index 97db2e8..9880ef2 100644 --- a/src/components/Calendar/CalendarSearch.tsx +++ b/src/components/Calendar/CalendarSearch.tsx @@ -61,7 +61,11 @@ function CalendarItem({ }} /> - {cal.cal["dav:name"]} + + {cal.cal["dav:name"] === "#default" + ? cal.owner.displayName + "'s calendar" + : cal.cal["dav:name"]} + {cal.owner.email} diff --git a/src/components/Calendar/CalendarSelection.tsx b/src/components/Calendar/CalendarSelection.tsx index 315084f..2454ae5 100644 --- a/src/components/Calendar/CalendarSelection.tsx +++ b/src/components/Calendar/CalendarSelection.tsx @@ -12,7 +12,7 @@ import IconButton from "@mui/material/IconButton"; import Checkbox from "@mui/material/Checkbox"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import CalendarSearch from "./CalendarSearch"; -import { Divider, Menu, MenuItem } from "@mui/material"; +import { Divider, ListItem, Menu, MenuItem } from "@mui/material"; import { removeCalendarAsync } from "../../features/Calendars/CalendarSlice"; import { DeleteCalendarDialog } from "./DeleteCalendarDialog"; @@ -41,13 +41,24 @@ function CalendarAccordion({ if (calendars.length === 0 && !defaultExpanded) return null; return ( - + } aria-controls={`${title}-content`} id={`${title}-header`} className="calendarListHeader" onClick={() => setExpended(!expended)} + sx={{ + "& .MuiAccordionSummary-content": { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + }, + }} > {title} {showAddButton && ( @@ -62,7 +73,7 @@ function CalendarAccordion({ )} - + {calendars.map((id) => ( -
+ - + -
+ { diff --git a/src/features/Calendars/CalendarApi.ts b/src/features/Calendars/CalendarApi.ts index 3eb6e7d..06d6f7c 100644 --- a/src/features/Calendars/CalendarApi.ts +++ b/src/features/Calendars/CalendarApi.ts @@ -64,6 +64,10 @@ export async function addSharedCalendar( body: JSON.stringify({ id: calId, ...cal.cal, + "dav:name": + cal.cal["dav:name"] === "#default" + ? cal.owner.displayName + "'s calendar" + : cal.cal["dav:name"], "calendarserver:source": { acl: cal.cal.acl, calendarHomeId: cal.cal.id, diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts index 9ad5b6a..797eb72 100644 --- a/src/features/Calendars/CalendarSlice.ts +++ b/src/features/Calendars/CalendarSlice.ts @@ -39,7 +39,6 @@ export const getCalendarsListAsync = createAsyncThunk< const rawCalendars = calendars._embedded["dav:calendar"]; for (const cal of rawCalendars) { - const name = cal["dav:name"]; const description = cal["caldav:description"]; let delegated = false; let source = cal["calendarserver:source"] @@ -51,8 +50,16 @@ export const getCalendarsListAsync = createAsyncThunk< delegated = true; } const id = source.replace("/calendars/", "").replace(".json", ""); + const ownerId = id.split("/")[0]; const visibility = getCalendarVisibility(cal["acl"]); - const ownerData: any = await getUserDetails(id.split("/")[0]); + const ownerData: any = await getUserDetails(ownerId); + const name = + ownerId !== user.id && cal["dav:name"] === "#default" + ? `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ + ownerData.lastname + }` + "'s calendar" + : cal["dav:name"]; + const color = { light: cal["apple:color"] ?? "#006BD8", dark: cal["X-TWAKE-Dark-theme-color"] ?? "#FFF", @@ -370,7 +377,12 @@ export const addSharedCalendarAsync = createAsyncThunk< }, link: `/calendars/${userId}/${calId}.json`, desc: cal.cal["caldav:description"], - name: cal.cal["dav:name"], + name: + ownerData.id !== userId && cal.cal["dav:name"] === "#default" + ? `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ + ownerData.lastname + }` + "'s calendar" + : cal.cal["dav:name"], owner: `${ownerData.firstname ? `${ownerData.firstname} ` : ""}${ ownerData.lastname }`,